Showing posts with label CSS. Show all posts
Showing posts with label CSS. Show all posts

Sunday, September 28, 2014

AngularJS: ng-repeat with conditioning styling

Well, in order to reduce the amount of work, you might be using quite a bit of 'ng-repeat' in your views/html files that uses angularJS. However, there might be a need to style the individual items differently. Therefore...


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Sunday, June 29, 2014

AngularJS: Simple Animation

Here's a simple example on ho to create an animation using AngularJS.


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Thursday, May 29, 2014

AngularJS: IE and inline dynamic style...

We saw this interesting bug with AngularJS and inline style with IE browsers. And we finally managed to find a workaround for this problem. And the solution requires ng-style and a separate function. :D


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Friday, May 16, 2014

AngularJS: 2D Array binding

Here's a simple example to demo 2D array binding with AngularJS.


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Thursday, April 10, 2014

AngularJS: Select element + filter function

If you are going to use a <select> element in your website that is going to build on top of AngularJS, and at the same time if you ended up using a mixture of normal <option> element and <select> element with ng-repeat, rather than using ng-show to hide some of the elements, it might be better to use a filter function.


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Saturday, March 29, 2014

AngularJS: Moment + timezone example

At my current workplace, they were using this javascript class to handle the time for different time zones, therefore I have created a simple example to showcase this class. :D

Main HTML file - index.html
<!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>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Moment Timezone</title>
</head>
<!-- stitch this with the module declare in Javascript -->
<body ng-app="myApp">
  <div ng-controller="SelectCtrl">The time in
    <select ng-model="selectedItem" ng-options="item.label for item in myData  | orderBy:'label'" ng-change="updateTime()"></select> is {{formattedTime}}.
  </div>
  <script type="text/javascript" src="js/angular.min.js"></script>
  <script type="text/javascript" src="js/app.js"></script>
  <script type="text/javascript" src="js/controller.js"></script>
  <script type="text/javascript" src="js/moment.min.js"></script>
  <script type="text/javascript" src="js/moment-timezone.min.js"></script>
  <script type="text/javascript" src="js/moment-timezone-data.js"></script>
</body>
</html>

Javascript file that stores the respective time zone data - moment-timezone-data.js
//The data of the time zone of the various time zone.
tzData = {
    "zones": {
        "Asia/Singapore": [
            "6:55:25 - LMT 1901_0_1 6:55:25",
            "6:55:25 - SMT 1905_5_1 6:55:25",
            "7 - MALT 1933_0_1 7",
            "7:20 - MALST 1936_0_1 7:20",
            "7:20 - MALT 1941_8_1 7:20",
            "7:30 - MALT 1942_1_16 7:30",
            "9 - JST 1945_8_12 9",
            "7:30 - MALT 1965_7_9 7:30",
            "7:30 - SGT 1982_0_1 7:30",
            "8 - SGT"
        ],
        "Australia/Sydney": [
            "10:4:52 - LMT 1895_1 10:4:52",
            "10 Aus EST 1971 10",
            "10 AN EST"
        ],
        "EST5EDT": [
            "-5 US E%sT"
        ],
        "Europe/Amsterdam": [
            "0:19:32 - LMT 1835 0:19:32",
            "0:19:32 Neth %s 1937_6_1 1:19:32",
            "0:20 Neth NE%sT 1940_4_16_0 0:20",
            "1 C-Eur CE%sT 1945_3_2_2 1",
            "1 Neth CE%sT 1977 1",
            "1 EU CE%sT"
        ],
        "Europe/London": [
            "-0:1:15 - LMT 1847_11_1_0 -0:1:15",
            "0 GB-Eire %s 1968_9_27 1",
            "1 - BST 1971_9_31_2",
            "0 GB-Eire %s 1996",
            "0 EU GMT/BST"
        ]
    },
    "rules": {
        "Aus": [
            "1917 1917 0 1 7 0:1 0 1",
            "1917 1917 2 25 7 2 0 0",
            "1942 1942 0 1 7 2 0 1",
            "1942 1942 2 29 7 2 0 0",
            "1942 1942 8 27 7 2 0 1",
            "1943 1944 2 0 8 2 0 0",
            "1943 1943 9 3 7 2 0 1"
        ],
        "AN": [
            "1971 1985 9 0 8 2 2 1",
            "1972 1972 1 27 7 2 2 0",
            "1973 1981 2 1 0 2 2 0",
            "1982 1982 3 1 0 2 2 0",
            "1983 1985 2 1 0 2 2 0",
            "1986 1989 2 15 0 2 2 0",
            "1986 1986 9 19 7 2 2 1",
            "1987 1999 9 0 8 2 2 1",
            "1990 1995 2 1 0 2 2 0",
            "1996 2005 2 0 8 2 2 0",
            "2000 2000 7 0 8 2 2 1",
            "2001 2007 9 0 8 2 2 1",
            "2006 2006 3 1 0 2 2 0",
            "2007 2007 2 0 8 2 2 0",
            "2008 9999 3 1 0 2 2 0",
            "2008 9999 9 1 0 2 2 1"
        ],
        "US": [
            "1918 1919 2 0 8 2 0 1 D",
            "1918 1919 9 0 8 2 0 0 S",
            "1942 1942 1 9 7 2 0 1 W",
            "1945 1945 7 14 7 23 1 1 P",
            "1945 1945 8 30 7 2 0 0 S",
            "1967 2006 9 0 8 2 0 0 S",
            "1967 1973 3 0 8 2 0 1 D",
            "1974 1974 0 6 7 2 0 1 D",
            "1975 1975 1 23 7 2 0 1 D",
            "1976 1986 3 0 8 2 0 1 D",
            "1987 2006 3 1 0 2 0 1 D",
            "2007 9999 2 8 0 2 0 1 D",
            "2007 9999 10 1 0 2 0 0 S"
        ],
        "Neth": [
            "1916 1916 4 1 7 0 0 1 NST",
            "1916 1916 9 1 7 0 0 0 AMT",
            "1917 1917 3 16 7 2 2 1 NST",
            "1917 1917 8 17 7 2 2 0 AMT",
            "1918 1921 3 1 1 2 2 1 NST",
            "1918 1921 8 1 8 2 2 0 AMT",
            "1922 1922 2 0 8 2 2 1 NST",
            "1922 1936 9 2 0 2 2 0 AMT",
            "1923 1923 5 1 5 2 2 1 NST",
            "1924 1924 2 0 8 2 2 1 NST",
            "1925 1925 5 1 5 2 2 1 NST",
            "1926 1931 4 15 7 2 2 1 NST",
            "1932 1932 4 22 7 2 2 1 NST",
            "1933 1936 4 15 7 2 2 1 NST",
            "1937 1937 4 22 7 2 2 1 NST",
            "1937 1937 6 1 7 0 0 1 S",
            "1937 1939 9 2 0 2 2 0",
            "1938 1939 4 15 7 2 2 1 S",
            "1945 1945 3 2 7 2 2 1 S",
            "1945 1945 8 16 7 2 2 0"
        ],
        "C-Eur": [
            "1916 1916 3 30 7 23 0 1 S",
            "1916 1916 9 1 7 1 0 0",
            "1917 1918 3 15 1 2 2 1 S",
            "1917 1918 8 15 1 2 2 0",
            "1940 1940 3 1 7 2 2 1 S",
            "1942 1942 10 2 7 2 2 0",
            "1943 1943 2 29 7 2 2 1 S",
            "1943 1943 9 4 7 2 2 0",
            "1944 1945 3 1 1 2 2 1 S",
            "1944 1944 9 2 7 2 2 0",
            "1945 1945 8 16 7 2 2 0",
            "1977 1980 3 1 0 2 2 1 S",
            "1977 1977 8 0 8 2 2 0",
            "1978 1978 9 1 7 2 2 0",
            "1979 1995 8 0 8 2 2 0",
            "1981 9999 2 0 8 2 2 1 S",
            "1996 9999 9 0 8 2 2 0"
        ],
        "EU": [
            "1977 1980 3 1 0 1 1 1 S",
            "1977 1977 8 0 8 1 1 0",
            "1978 1978 9 1 7 1 1 0",
            "1979 1995 8 0 8 1 1 0",
            "1981 9999 2 0 8 1 1 1 S",
            "1996 9999 9 0 8 1 1 0"
        ],
        "GB-Eire": [
            "1916 1916 4 21 7 2 2 1 BST",
            "1916 1916 9 1 7 2 2 0 GMT",
            "1917 1917 3 8 7 2 2 1 BST",
            "1917 1917 8 17 7 2 2 0 GMT",
            "1918 1918 2 24 7 2 2 1 BST",
            "1918 1918 8 30 7 2 2 0 GMT",
            "1919 1919 2 30 7 2 2 1 BST",
            "1919 1919 8 29 7 2 2 0 GMT",
            "1920 1920 2 28 7 2 2 1 BST",
            "1920 1920 9 25 7 2 2 0 GMT",
            "1921 1921 3 3 7 2 2 1 BST",
            "1921 1921 9 3 7 2 2 0 GMT",
            "1922 1922 2 26 7 2 2 1 BST",
            "1922 1922 9 8 7 2 2 0 GMT",
            "1923 1923 3 16 0 2 2 1 BST",
            "1923 1924 8 16 0 2 2 0 GMT",
            "1924 1924 3 9 0 2 2 1 BST",
            "1925 1926 3 16 0 2 2 1 BST",
            "1925 1938 9 2 0 2 2 0 GMT",
            "1927 1927 3 9 0 2 2 1 BST",
            "1928 1929 3 16 0 2 2 1 BST",
            "1930 1930 3 9 0 2 2 1 BST",
            "1931 1932 3 16 0 2 2 1 BST",
            "1933 1933 3 9 0 2 2 1 BST",
            "1934 1934 3 16 0 2 2 1 BST",
            "1935 1935 3 9 0 2 2 1 BST",
            "1936 1937 3 16 0 2 2 1 BST",
            "1938 1938 3 9 0 2 2 1 BST",
            "1939 1939 3 16 0 2 2 1 BST",
            "1939 1939 10 16 0 2 2 0 GMT",
            "1940 1940 1 23 0 2 2 1 BST",
            "1941 1941 4 2 0 1 2 2 BDST",
            "1941 1943 7 9 0 1 2 1 BST",
            "1942 1944 3 2 0 1 2 2 BDST",
            "1944 1944 8 16 0 1 2 1 BST",
            "1945 1945 3 2 1 1 2 2 BDST",
            "1945 1945 6 9 0 1 2 1 BST",
            "1945 1946 9 2 0 2 2 0 GMT",
            "1946 1946 3 9 0 2 2 1 BST",
            "1947 1947 2 16 7 2 2 1 BST",
            "1947 1947 3 13 7 1 2 2 BDST",
            "1947 1947 7 10 7 1 2 1 BST",
            "1947 1947 10 2 7 2 2 0 GMT",
            "1948 1948 2 14 7 2 2 1 BST",
            "1948 1948 9 31 7 2 2 0 GMT",
            "1949 1949 3 3 7 2 2 1 BST",
            "1949 1949 9 30 7 2 2 0 GMT",
            "1950 1952 3 14 0 2 2 1 BST",
            "1950 1952 9 21 0 2 2 0 GMT",
            "1953 1953 3 16 0 2 2 1 BST",
            "1953 1960 9 2 0 2 2 0 GMT",
            "1954 1954 3 9 0 2 2 1 BST",
            "1955 1956 3 16 0 2 2 1 BST",
            "1957 1957 3 9 0 2 2 1 BST",
            "1958 1959 3 16 0 2 2 1 BST",
            "1960 1960 3 9 0 2 2 1 BST",
            "1961 1963 2 0 8 2 2 1 BST",
            "1961 1968 9 23 0 2 2 0 GMT",
            "1964 1967 2 19 0 2 2 1 BST",
            "1968 1968 1 18 7 2 2 1 BST",
            "1972 1980 2 16 0 2 2 1 BST",
            "1972 1980 9 23 0 2 2 0 GMT",
            "1981 1995 2 0 8 1 1 1 BST",
            "1981 1989 9 23 0 1 1 0 GMT",
            "1990 1995 9 22 0 1 1 0 GMT"
        ]
    },
    "links": {}
};

moment.tz.add(tzData);

Javascript file that stores our AngularJS Application - app.js
// declare a module
var myApp = this.angular.module('myApp', ['myAppControllers']);
Javascript file that stores our Angularjs Controllers - controller.js
// declare a controller
angular.module('myAppControllers', []).
  controller('SelectCtrl', function ($scope) {
    //the selections for the time zone drop down
    $scope.myData = [{
      label: "Singapore",
      value: "Asia/Singapore"
    }, {
      label: "Sydney",
      value: "Australia/Sydney"
    }, {
      label: "EST5EDT",
      value: "EST5EDT"
    }, {
      label: "Amsterdam",
      value: "Europe/Amsterdam"
    }, {
      label: "London",
      value: "Europe/London"
    }];

 //Preselect the first item in the array
    $scope.selectedItem = $scope.myData[0];
    $scope.formattedTime = "";
    $scope.timer;
 //This function will pick up the selected item from the
 //drop down and display the corresponding time of the
 //time zone
    $scope.updateTime = function () {
   var tempDate;
   var strTz = $scope.selectedItem.value;
      tempDate = moment.tz(strTz);
      $scope.formattedTime = tempDate.format('MMMM Do YYYY, h:mm:ss a');
   $scope.$apply();
    }
    $scope.updateTime();
 //We will run the function updateTime every second
    setInterval(function () {
      $scope.updateTime()
    }, 1000);
  });
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.
~ Click here to find out more about 'AngularJS'.
* Click here to find out more about 'moment.js'.
^ Click here to find out more about 'Moment Timezone'.
~ Click here to generate the data for the respective time zone for 'Moment Timezone'.

Wednesday, March 12, 2014

AngularJS: Select + Option in Angular

If you are going to use a <select> element in your website that is going to build on top of AngularJS, rather than using a mixture of <select> and <option> element, it would be best if you use a combination of <select> and the attribute 'ng-options'. As for the reason why, you can take a look at the demo below, and take a look at it again across browsers like 'Internet Explorer 8/9', 'Mozilla Firefox', etc...


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Tuesday, March 4, 2014

AngularJS: Alternate Background Row Styles

When you have a table with fixed contents, it is pretty easy for you to apply styling that applies different set of styles on alternate table rows. However, things get more and more tricky when you are hiding and showing some of the rows. Therefore, here's a simple example that I have created using 'AngularJS' that helps you to overcome the problem of alternate background styles + hidden rows.


* Click here to access the demo that I have created on 'JSFiddle'.
^ Click here to test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code
  editor.

Monday, February 24, 2014

Hiding a Option element in your webpage

By applying a style="display:none" to the <option> element in your webpage will not give you the desired results across all the browsers. Therefore, you either remove or add the <option> element when needed or create 2 different set of <select> element to provide the user the correct set of menu.

Here's the source code of the page that I have created, try viewing it using different browsers like 'Internet Explorer', 'Mozilla Firefox' and 'Google Chrome' and you can spot the difference.
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Hide a menu option</title>
</head>
<body>
Fruits:
<select>
    <option value="apple">Apple</option>
    <option value="orange">Orange</option>
    <option value="pear" style="display:none">Pear</option>
    <option value="pineapple">Pineapple</option>
</select>
</body>
</html>
* Click here for the demo shown in this post.

Friday, August 30, 2013

Flex: A Simple Slider with a Labeled Button

Time to move back to the easier stuff. In the older versions of Flex, you would need to play around a few properties and create a few components in order to create a similar UI component. However, in the newer versions of Flex, some sophisticated stuff back then have now been simplified. However that doesn't mean that the development time can reduce greatly, it simply means that you don't need to waste too much time figuring out these small little stuff.

The source codes of the main application file - SimpleSliderWithValue.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx">
 <fx:Style source="css/style.css"/>
 <s:HGroup width="100%" 
     height="100%" 
     verticalAlign="middle"
     horizontalAlign="center">
  <s:VSlider minimum="0"
       maximum="100"
       value="50"  
       showDataTip="false" 
       height="200"
       styleName="customSliderV"/>
   <s:HSlider minimum="0"
       maximum="100"
       value="50" 
       showDataTip="false" 
       width="200" 
       styleName="customSliderH"/>
 </s:HGroup>
</s:Application>

Skin Class for the Horizontal Slider - skins/CustomHSliderWithLabel.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.
-->

<!--- The default skin class for the Spark HSlider component. The thumb and track skins are defined by the
HSliderThumbSkin and HSliderTrackSkin classes, respectively.  

       @see spark.components.HSlider
       @see spark.skins.spark.HSliderThumbSkin
       @see spark.skins.spark.HSliderTrackSkin
                
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minHeight="11" alpha.disabled="0.5">

    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.HSlider")]
    ]]>
    </fx:Metadata> 
    
    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For slider, the skin itself is colorized but the individual parts are not. */
        static private const exclusions:Array = ["track", "thumb"];

        /**
         * @private
         */  
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
    </fx:Script>
    
    <fx:Script>
        /**
         *  @private
         */  
        override protected function measure() : void
        {
            // Temporarily move the thumb to the left of the Slider so measurement
            // doesn't factor in its x position. This allows resizing the
            // HSlider to less than 100px in width. 
            var thumbPos:Number = thumb.getLayoutBoundsX();
            thumb.setLayoutBoundsPosition(0, thumb.getLayoutBoundsY());
            super.measure();
            thumb.setLayoutBoundsPosition(thumbPos, thumb.getLayoutBoundsY());
        }
    </fx:Script>
    
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
    
    <fx:Declarations>
        <!--- The tooltip used in the mx.controls.Slider control. 
               To customize the DataTip's appearance, create a custom HSliderSkin class.-->
        <fx:Component id="dataTip">     
           <s:DataRenderer minHeight="24" minWidth="40" y="-34">  
              <s:Rect top="0" left="0" right="0" bottom="0">
                    <s:fill>
                        <s:SolidColor color="0x000000" alpha=".9"/>
                    </s:fill>
                    <s:filters>
                        <s:DropShadowFilter angle="90" color="0x999999" distance="3"/>
                    </s:filters>
                </s:Rect>
                <s:Label id="labelDisplay" text="{data}"
                         horizontalCenter="0" verticalCenter="1"
                         left="5" right="5" top="5" bottom="5"
                         textAlign="center" verticalAlign="middle"
                         fontWeight="normal" color="white" fontSize="11">
                </s:Label>
            </s:DataRenderer>
       </fx:Component>
    </fx:Declarations>
    
    <!--- 
   The default skin class is HSliderTrackSkin. 
   @copy spark.components.supportClasses.TrackBase#track
   @see spark.skins.spark.HSliderTrackSkin 
 
   We changing the size of the track so that it will
   become very thin.
 -->
    <s:Button id="track" left="0" right="0" top="8" bottom="8" minWidth="33" width="100" 
              tabEnabled="false"
              skinClass="spark.skins.spark.HSliderTrackSkin" />
              
    <!--- 
   The default skin class is HSliderThumbSkin.
         @copy spark.components.supportClasses.TrackBase#thumb 
         @see spark.skins.spark.HSliderThumbSkin
 
   We changing the Button Skin Class to 
   spark.skins.spark.ButtonSkin so that we 
   can bind the label to the thumb.
 -->
    <s:Button id="thumb" top="0" bottom="0" width="45" height="20" 
              tabEnabled="false" styleName="customSliderHThumb" 
     label="{hostComponent.value}" />
</s:SparkSkin>

Skin Class for the Vertical Slider - skins/CustomVSliderWithLabel.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.
-->

<!--- The default skin class for the Spark VSlider component. The thumb and track skins are defined by the
VSliderThumbSkin and VSliderTrackSkin classes, respectively.  

       @see spark.components.VSlider
       @see spark.skins.spark.VSliderThumbSkin
       @see spark.skins.spark.VSliderTrackSkin
        
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="11" alpha.disabled="0.5">

    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.VSlider")]
    ]]>
    </fx:Metadata> 
    
    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For slider, the skin itself is colorized but the individual parts are not. */
        static private const exclusions:Array = ["track", "thumb"];

        /**
         * @private
         */   
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
    </fx:Script>
 
    <fx:Script>
        /**
         *  @private
         */  
        override protected function measure() : void
        {
            // Temporarily move the thumb to the top of the Slider so measurement
            // doesn't factor in its y position. This allows resizing the
            // VSlider to less than 100px in height. 
            var thumbPos:Number = thumb.getLayoutBoundsY();
            thumb.setLayoutBoundsPosition(thumb.getLayoutBoundsX(), 0);
            super.measure();
            thumb.setLayoutBoundsPosition(thumb.getLayoutBoundsX(), thumbPos);
        }
    </fx:Script>
    
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
    
    <fx:Declarations>
        <!--- The tooltip used in the mx.controls.Slider control.
              To customize the DataTip's appearance, create a custom VSliderSkin class. -->
        <fx:Component id="dataTip">
            <s:DataRenderer minHeight="24" minWidth="40" x="20"> 
                <s:Rect top="0" left="0" right="0" bottom="0">
                    <s:fill>
                        <s:SolidColor color="0x000000" alpha=".9"/>
                    </s:fill>
                    <s:filters>
                        <s:DropShadowFilter angle="90" color="0x999999" distance="3"/>
                    </s:filters>
                </s:Rect>
                <s:Label id="labelDisplay" text="{data}"
                         horizontalCenter="0" verticalCenter="1"
                         left="5" right="5" top="5" bottom="5"
                         textAlign="center" verticalAlign="middle"
                         fontWeight="normal" color="white" fontSize="11">
                </s:Label>
            </s:DataRenderer>
        </fx:Component>
    </fx:Declarations>
    
    <!--- 
   The default skin class is VSliderTrackSkin.
   @copy spark.components.supportClasses.TrackBase#track 
   @see spark.skins.spark.VSliderTrackSkin 
 
   We changing the size of the track so that it will
   become very thin. 
 -->
    <s:Button id="track" left="17" right="17" top="0" bottom="0" minHeight="33" height="100"
              tabEnabled="false"
              skinClass="spark.skins.spark.VSliderTrackSkin" />
              
    <!--- 
   The default skin class is VSliderThumbSkin. 
   @copy spark.components.supportClasses.TrackBase#thumb
   @see spark.skins.spark.VSliderThumbSkin
   
   We changing the Button Skin Class to 
   spark.skins.spark.ButtonSkin so that we 
   can bind the label to the thumb.
 -->
    <s:Button id="thumb" left="0" right="0" width="36" height="27"
              tabEnabled="false" styleName="customSliderVThumb" 
     label="{hostComponent.value}" />
</s:SparkSkin>

The main CSS file - css/style.css
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

s|VSlider.customSliderV{
 skinClass: ClassReference("skins.CustomVSliderWithLabel");
}
s|HSlider.customSliderH{
 skinClass: ClassReference("skins.CustomHSliderWithLabel");
}
.customSliderHThumb,.customSliderVThumb{
 skinClass: ClassReference("spark.skins.spark.ButtonSkin");
}
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Thursday, August 8, 2013

Flex: Creating a Checkbox with 3 states...

There will be situations that requires a list of checkboxes and you are giving the user the option of selecting and unselecting the individual options. However, the normal checkbox might work for the individual selections but it will not work nicely for the header. Therefore...

Main Application Source Code - Simple3StateCheckBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx" 
      creationComplete="creationCompleteHandler(event)">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <fx:Style source="css/style.css"/>
 <fx:Script>
  <![CDATA[
   import events.CustomCheckBoxEvents;
   
   import mx.collections.ArrayCollection;
   import mx.events.FlexEvent;
   
   import object.SingletonObject;
   
   /**
    * We are using a singleton object to store the objects/data.
    */
   private var dataObj:SingletonObject = 
    SingletonObject.getInstance();
   /**
    * Upon creationComplete, we need to add all the Listeners
    * and check the appropriate state that we should be
    * displaying for the header.
    */
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    this.addEventListener(
     CustomCheckBoxEvents.SELECT_ALL_ITEMS,
     checkBoxEvent);
    this.addEventListener(
     CustomCheckBoxEvents.UNSELECT_ALL_ITEMS,
     checkBoxEvent);
    this.addEventListener(
     CustomCheckBoxEvents.SELECT_AN_ITEM,
     checkBoxEvent);
    this.addEventListener(
     CustomCheckBoxEvents.UNSELECT_AN_ITEM,
     checkBoxEvent);
    updateHeaderState();
   }
   
   /**
    * All the events are handled over here.
    */
   private function checkBoxEvent(event:CustomCheckBoxEvents):void
   {
    for each(var item:Object in dataObj.expenses)
    {
     if(event.type == CustomCheckBoxEvents.SELECT_ALL_ITEMS)
     {
      item.selected = true;
     }else if(event.type == CustomCheckBoxEvents.UNSELECT_ALL_ITEMS)
     {
      item.selected = false;
     }else if(item.id == event.data.id)
     {
      if(event.type == 
       CustomCheckBoxEvents.SELECT_AN_ITEM)
      {
       item.selected = true;
      }else if(event.type == 
       CustomCheckBoxEvents.UNSELECT_AN_ITEM)
      {
       item.selected = false;
      }
     }
    }
    dataObj.expenses.refresh();
    updateHeaderState();
   }
   
   /**
    * Function to determine that best state that we are
    * showing for the header.
    */
   private function updateHeaderState():void
   {
    var count:Number = 0;
    var maxCount:Number = 0;
    for each(var item:Object in dataObj.expenses)
    {
     maxCount ++;
     if(item.selected)
     {
      count ++;
     }
    }
    if(count == 0)
    {
     dataObj.selectedState = 0;
    }else if(count == maxCount)
    {
     dataObj.selectedState = 2;
    }else{
     dataObj.selectedState = 1;
    }
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%"
     height="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
  <s:DataGrid width="50%"
      height="50%" 
     dataProvider="{dataObj.expenses}">
   <s:columns>
    <s:ArrayList>
     <s:GridColumn dataField="selected" 
          width="20"
          headerRenderer="renderers.CustomHeaderCheckBoxRenderer"
          itemRenderer="renderers.CustomCheckBoxRenderer"/>
     <s:GridColumn dataField="amount"/>
    </s:ArrayList>
   </s:columns>
  </s:DataGrid>
 </s:VGroup>
</s:Application>

Event class for the checkbox - events/CustomCheckBoxEvents.as
package events
{
 import flash.events.Event;
 
 public class CustomCheckBoxEvents extends Event
 {
  //All the different event type
  public static const SELECT_ALL_ITEMS:String = 
   "selectAllItems";
  public static const UNSELECT_ALL_ITEMS:String = 
   "unselectAllItems";
  public static const SELECT_AN_ITEM:String = 
   "selectAnItem";
  public static const UNSELECT_AN_ITEM:String = 
   "unselectAnItem";
  
  private var _data:Object = null;

  public function get data():Object
  {
   return _data;
  }

  public function set data(value:Object):void
  {
   _data = value;
  }
  
  public function CustomCheckBoxEvents(type:String, tempData:Object = null, bubbles:Boolean=true, cancelable:Boolean=false)
  {
   super(type, bubbles, cancelable);
   _data = tempData;
  }
  
  override public function clone():Event
  {
   // TODO Auto Generated method stub
   return new CustomCheckBoxEvents(type, data, bubbles, cancelable);
  }
 }
}

Singleton Object class to store the neccessary data - object/SingletonObject.as
package object
{
 import mx.collections.ArrayCollection;

 public class SingletonObject
 {
  private static var _instance:SingletonObject=null;
  
  /**
   * You need the following functions to create a
   * singleton Object. SingletonObject(e:SingletonEnforcer)
   * and getInstance():SingletonObject
   * Rather than using new SingletonObject to create a new
   * object of the class, you need to use
   * SingletonObject.getInstance() to point to the Singleton
   * class.
   */
  public function SingletonObject(e:SingletonEnforcer){
   trace("new singleton object created");
  }

  public static function getInstance():SingletonObject{
   if(_instance==null){
    _instance=new SingletonObject(new SingletonEnforcer);
   }
   return _instance;
  }
  
  /**
   * Here's our data for the DataGrid.
   */
  private var _expenses:ArrayCollection = new ArrayCollection([
   {selected:true, id:0, amount:2000},
   {selected:true, id:1, amount:1000},
   {selected:true, id:2, amount:100},
   {selected:true, id:3, amount:450},
   {selected:true, id:4, amount:100},
   {selected:true, id:5, amount:200}
  ]);
  
  [Bindable]
  public function get expenses():ArrayCollection
  {
   return _expenses;
  }
  
  public function set expenses(value:ArrayCollection):void
  {
   _expenses = value;
  }
  
  private var _selectedState:Number = 0;
  
  [Bindable]
  public function get selectedState():Number
  {
   return _selectedState;
  }

  public function set selectedState(value:Number):void
  {
   _selectedState = value;
  }
 }
}

/**
 * This class is needed in creating a singleton class.
 */
class SingletonEnforcer{
 
}

Renderers class for the header that comes with a custom checkbox with 3 different states - renderers/CustomHeaderCheckBoxRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:DefaultGridHeaderRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx" 
        xmlns:component="renderers.component.*" 
        width="100%" click="clickHandler(event)">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import object.SingletonObject;
   /**
    * We are using a singleton object to store the objects/data.
    */
   private var dataObj:SingletonObject = 
    SingletonObject.getInstance();
   
   protected function clickHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
   }
   
  ]]>
 </fx:Script>
 <s:states>
  <s:State name="normal" />
  <s:State name="hovered" />
  <s:State name="down" />
 </s:states>     
 
 <!-- layer 1: shadow -->
 <!--- @private -->
 <s:Rect id="shadow" left="-1" right="-1" top="-1" bottom="-1" radiusX="2">
  <s:fill>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0x000000" 
         color.down="0xFFFFFF"
         alpha="0.01"
         alpha.down="0" />
    <s:GradientEntry color="0x000000" 
         color.down="0xFFFFFF" 
         alpha="0.07"
         alpha.down="0.5" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>
 
 <!-- layer 2: fill -->
 <!--- @private -->
 <s:Rect id="fill" left="0" right="0" top="0" bottom="0">
  <s:fill>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFFF" 
         color.hovered="0xBBBDBD" 
         color.down="0xAAAAAA" 
         alpha="0.85" />
    <s:GradientEntry color="0xD8D8D8" 
         color.hovered="0x9FA0A1" 
         color.down="0x929496" 
         alpha="0.85" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>
 
 <!-- layer 3: fill lowlight -->
 <!--- @private -->
 <s:Rect id="lowlight" left="0" right="0" top="0" bottom="0">
  <s:fill>
   <s:LinearGradient rotation="270">
    <s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627" />
    <s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099" />
    <s:GradientEntry color="0x000000" ratio="0.48001" alpha="0" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>
 
 <!-- layer 4: fill highlight -->
 <!--- @private -->
 <s:Rect id="highlight" left="0" right="0" top="0" bottom="0">
  <s:fill>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFFF"
         ratio="0.0"
         alpha="0.33" 
         alpha.hovered="0.22" 
         alpha.down="0.12"/>
    <s:GradientEntry color="0xFFFFFF"
         ratio="0.48"
         alpha="0.33"
         alpha.hovered="0.22"
         alpha.down="0.12" />
    <s:GradientEntry color="0xFFFFFF"
         ratio="0.48001"
         alpha="0" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>  
 
 <!-- layer 5: highlight stroke (all states except down) -->
 <!--- @private -->
 <s:Rect id="highlightStroke" left="0" right="0" top="0" bottom="0" excludeFrom="down">
  <s:stroke>
   <s:LinearGradientStroke rotation="90" weight="1">
    <s:GradientEntry color="0xFFFFFF" alpha.hovered="0.22" />
    <s:GradientEntry color="0xD8D8D8" alpha.hovered="0.22" />
   </s:LinearGradientStroke>
  </s:stroke>
 </s:Rect>
 
 <!-- layer 6: highlight stroke (down state only) -->
 <!--- @private -->
 <s:Rect id="hldownstroke1" left="0" right="0" top="0" bottom="0" includeIn="down">
  <s:stroke>
   <s:LinearGradientStroke rotation="90" weight="1">
    <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.0" />
    <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.001" />
    <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.0011" />
    <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.965" />
    <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.9651" />
   </s:LinearGradientStroke>
  </s:stroke>
 </s:Rect>
 <!--- @private -->
 <s:Rect id="hldownstroke2" left="1" right="1" top="1" bottom="1" includeIn="down">
  <s:stroke>
   <s:LinearGradientStroke rotation="90" weight="1">
    <s:GradientEntry color="0x000000" alpha="0.09" ratio="0.0" />
    <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.0001" />
   </s:LinearGradientStroke>
  </s:stroke>
 </s:Rect>
 <s:VGroup verticalAlign="middle" 
     horizontalAlign="center" 
     width="100%"
     height="100%">
  <component:CustomCheckBox styleName="customCheckBox"
          selectedValue="{dataObj.selectedState}"/>
 </s:VGroup>
</s:DefaultGridHeaderRenderer>


Custom checkbox that supports 3 different states - renderers/component/CustomCheckBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:CheckBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx" 
   click="clickHandler(event)" 
   mouseOver="mouseOverHandler(event)" 
   mouseDown="mouseDownHandler(event)" 
   mouseOut="mouseOutHandler(event)">
 <!-- Declaring all the different types of state in this component -->
 <fx:Metadata>
  [SkinState("up")]
  [SkinState("over")]
  [SkinState("down")]
  [SkinState("disabled")]
  [SkinState("upAndSelected")]
  [SkinState("overAndSelected")]
  [SkinState("downAndSelected")]
  [SkinState("disabledAndSelected")]
  [SkinState("upAndSemiSelected")]
  [SkinState("overAndSemiSelected")]
  [SkinState("downAndSemiSelected")]
  [SkinState("disabledAndSemiSelected")]
 </fx:Metadata>
 <fx:Script>
  <![CDATA[
   import events.CustomCheckBoxEvents;
   /**
    * Rather than select and unselected state,
    * we need 3 different states now.
    * 
    * 0 - not selected
    * 1 - semi selected
    * 2 - selected
    * 
    * @default 0
    */
   private var _selectedValue:Number = 0;

   public function get selectedValue():Number
   {
    return _selectedValue;
   }

   public function set selectedValue(value:Number):void
   {
    _selectedValue = value;
    updateState();
   }
   
   /**
    * For storing the component state
    * 
    * 0 - up
    * 1 - over
    * 2 - down
    * 
    * @default 0
    */
   private var currentComponentState:Number = 0;
   
   /**
    * For the skin file to find out the state that it
    * should be displaying.
    */
   override protected function getCurrentSkinState():String
   {
    return this.currentState;
   }
   
   /**
    * Upon clicking on this component, we need to raise
    * a few events.
    */
   override protected function clickHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    switch (_selectedValue)
    {
     //when unselected
     case 0:
      _selectedValue = 2;
      this.dispatchEvent(
       new CustomCheckBoxEvents(
        CustomCheckBoxEvents.SELECT_ALL_ITEMS));
      break;
     //when semi selected
     case 1:
      _selectedValue = 2;
      this.dispatchEvent(
       new CustomCheckBoxEvents(
        CustomCheckBoxEvents.SELECT_ALL_ITEMS));
      break;
     //when selected
     case 2:
      _selectedValue = 0;
      this.dispatchEvent(
       new CustomCheckBoxEvents(
        CustomCheckBoxEvents.UNSELECT_ALL_ITEMS));
      break;
    }
    updateState();
   }
   
   /**
    * Upon mouse over on this component, we need to update
    * the state.
    */
   protected function mouseOverHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    currentComponentState = 1;
    updateState();
   }
   
   /**
    * Upon mouse down on this component, we need to update
    * the state.
    */
   protected function mouseDownHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    currentComponentState = 2;
    updateState();
   }
   
   /**
    * Upon mouse out on this component, we need to update
    * the state.
    */
   protected function mouseOutHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    currentComponentState = 0;
    updateState();
   }
   
   private function updateState():void
   {
    var tempStr:String = "";
    switch(_selectedValue)
    {
     //when unselected
     case 0:
      tempStr = "";
      break;
     //when semi selected
     case 1:
      tempStr = "AndSemiSelected";
      break;
     //when selected
     case 2:
      tempStr = "AndSelected";
      break;
    }
    if(this.enabled)
    {
     switch(currentComponentState)
     {
      //when mouse out
      case 0:
       tempStr = "up" + tempStr;
       break;
      //when mouse over
      case 1:
       tempStr = "over" + tempStr;
       break;
      //when mouse down
      case 2:
       tempStr = "down" + tempStr;
       break;
     }
    }else{
     tempStr = "disabled" + tempStr;
    }
    this.currentState = tempStr;
   }
  ]]>
 </fx:Script>
 <!-- 
  Upon swaping to these states, we need to call the function
  invalidateSkinState() to update the skin immediately.
 -->
 <s:states>
  <s:State name="up" enterState="invalidateSkinState()"/>
  <s:State name="over" enterState="invalidateSkinState()"/>
  <s:State name="down" enterState="invalidateSkinState()"/>
  <s:State name="disabled" enterState="invalidateSkinState()"/>
  <s:State name="upAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="overAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="downAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="disabledAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="upAndSemiSelected" enterState="invalidateSkinState()"/>
  <s:State name="overAndSemiSelected" enterState="invalidateSkinState()"/>
  <s:State name="downAndSemiSelected" enterState="invalidateSkinState()"/>
  <s:State name="disabledAndSemiSelected" enterState="invalidateSkinState()"/>
 </s:states>
</s:CheckBox>

Skin class for the custom checkbox - skins/CustomCheckBoxSkin.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.

-->

<!--- The default skin class for the Spark CheckBox component.  

      @see spark.components.CheckBox
        
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
    alpha.disabledStates="0.5">
 <fx:Metadata>[HostComponent("renderers.component.CustomCheckBox")]</fx:Metadata>

    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For button, the graphics are colorized but the label is not. */
        static private const exclusions:Array = ["labelDisplay", "check"];

       /** 
        * @private 
        */     
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /* Define the symbol fill items that should be colored by the "symbolColor" style. */
        static private const symbols:Array = ["checkMarkFill", "semiCheckMarkFill"];

       /**
        * @private 
        */
        override public function get symbolItems():Array {return symbols};
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
    </fx:Script>
    
    <fx:Script>
        <![CDATA[
            /** 
             * @private 
             */     
            private static const focusExclusions:Array = ["labelDisplay"];

            /**
             * @private
             */
            override public function get focusSkinExclusions():Array { return focusExclusions;};
        ]]>
    </fx:Script>
    
 <!--
  All the states of this component.
 -->
    <s:states>
        <s:State name="up" />
        <s:State name="over" stateGroups="overStates" />
        <s:State name="down" stateGroups="downStates" />
        <s:State name="disabled" stateGroups="disabledStates" />
        <s:State name="upAndSelected" stateGroups="selectedStates" />
        <s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
        <s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
        <s:State name="disabledAndSelected" stateGroups="disabledStates, selectedStates" />
  <s:State name="upAndSemiSelected" stateGroups="semiSelectedStates" />
  <s:State name="overAndSemiSelected" stateGroups="overStates, semiSelectedStates" />
  <s:State name="downAndSemiSelected" stateGroups="downStates, semiSelectedStates" />
  <s:State name="disabledAndSemiSelected" stateGroups="disabledStates, semiSelectedStates" />  
    </s:states>
    
    <s:Group verticalCenter="0" width="13" height="13" layoutDirection="ltr">
        <!-- drop shadow -->
        <s:Rect left="-1" top="-1" right="-1" bottom="-1">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0x000000" 
                                   color.downStates="0xFFFFFF"
                                   alpha="0.011"
                                   alpha.downStates="0" />
                    <s:GradientEntry color="0x000000" 
                                   color.downStates="0xFFFFFF" 
                                   alpha="0.121"
                                   alpha.downStates="0.57" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
        
        <!-- fill -->
        <s:Rect left="1" top="1" right="1" bottom="1">
            <s:fill>
                <s:LinearGradient rotation="90">
                    <s:GradientEntry color="0xFFFFFF" 
                                   color.overStates="0xBBBDBD" 
                                   color.downStates="0xAAAAAA" 
                                   alpha="0.85" />
                    <s:GradientEntry color="0xD8D8D8" 
                                   color.overStates="0x9FA0A1" 
                                   color.downStates="0x929496" 
                                   alpha="0.85" />
                </s:LinearGradient>
            </s:fill>
        </s:Rect>
        
        <!-- fill highlight -->
        <s:Rect left="1" right="1" top="1" height="5">
            <s:fill>
                <s:SolidColor color="0xFFFFFF" alpha="0.33" alpha.downStates="0" />
            </s:fill>
        </s:Rect>
        
        <!-- layer 6: highlight stroke (all states except down) -->
        <s:Rect left="1" right="1" top="1" bottom="1" excludeFrom="downStates">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0xFFFFFF" alpha.overStates="0.33" />
                    <s:GradientEntry color="0xFFFFFF" alpha="0.12" alpha.overStates="0.0396" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
        
        <!-- layer 6: highlight stroke (down state only) -->
        <s:Rect left="1" top="1" bottom="1" width="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.07" />
            </s:fill>
        </s:Rect>
        <s:Rect right="1" top="1" bottom="1" width="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.07" />
            </s:fill>
        </s:Rect>
        <s:Rect left="1" top="1" right="1" height="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.25" />
            </s:fill>
        </s:Rect>
        <s:Rect left="1" top="2" right="1" height="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.09" />
            </s:fill>
        </s:Rect>
        
        <!-- border - put on top of the fill so it doesn't disappear when scale is less than 1 -->
        <s:Rect left="0" top="0" right="0" bottom="0">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0x000000" 
                                   alpha="0.5625"
                                   alpha.downStates="0.6375" />
                    <s:GradientEntry color="0x000000" 
                                   alpha="0.75"
                                   alpha.downStates="0.85" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
    
        <!-- checkmark -->
        <!--- The checkmark in the box for this skin. To create a custom check mark, create a custom skin class. -->
        <s:Path left="2" top="0" includeIn="selectedStates" id="check" itemCreationPolicy="immediate"
                data="M 9.2 0.1 L 4.05 6.55 L 3.15 5.0 L 0.05 5.0 L 4.6 9.7 L 12.05 0.1 L 9.2 0.1">        
            <s:fill>
                <!--- 
                    @private 
                    The solid color fill for the CheckBox's checkmark. The default alpha is .9, and the default fill color is 0x000000. 
                -->
                <s:SolidColor id="checkMarkFill" color="0" alpha="0.8" />
            </s:fill>
        </s:Path>
  
  <!-- semi selected checkmark -->
  <!--- The checkmark in the box for this skin. To create a custom check mark, create a custom skin class. -->
  <s:Path left="2" top="2" includeIn="semiSelectedStates" id="semiCheck" itemCreationPolicy="immediate"
    data="M 1 1 L 10 1 L 10 10 L 1 10 L 1 1">        
   <s:fill>
    <!--- 
    @private 
    The solid color fill for the CheckBox's checkmark. The default alpha is .9, and the default fill color is 0x000000. 
    -->
    <s:SolidColor id="semiCheckMarkFill" color="0" alpha="0.8" />
   </s:fill>
  </s:Path>
    </s:Group>

    <!-- Label -->
    <!--- @copy spark.components.supportClasses.ButtonBase#labelDisplay -->
    <s:Label id="labelDisplay"
             textAlign="start"
             verticalAlign="middle"
             maxDisplayedLines="1"
             left="18" right="0" top="3" bottom="3" 
    verticalCenter="2" visible="false"/>
</s:SparkSkin>

Renderers class for the individual items that comes with a normal checkbox - CustomCheckBoxRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
     xmlns:s="library://ns.adobe.com/flex/spark" 
     xmlns:mx="library://ns.adobe.com/flex/mx" 
     implements="spark.components.gridClasses.IGridItemRenderer"
     width="100%">
 
 <fx:Script>
  <![CDATA[
   import events.CustomCheckBoxEvents;
   /** 
    * Upon setting the data into the renderer, we need to
    * change the state of the checkbox.
    */
   override public function set data(value:Object):void
   {
    super.data = value;
    chk.selected = data[this.column.dataField]
   } 
   
   /**
    * Upon cliking on the check box, we need to dispatch
    * some events.
    */   
   protected function chk_clickHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    if(chk.selected)
    {
     this.dispatchEvent(
      new CustomCheckBoxEvents(
       CustomCheckBoxEvents.SELECT_AN_ITEM,
      this.data));
    }else{
     
     this.dispatchEvent(
      new CustomCheckBoxEvents(
       CustomCheckBoxEvents.UNSELECT_AN_ITEM,
      this.data));
    }
   }
   
  ]]>
 </fx:Script>
 <s:VGroup verticalAlign="middle" 
     horizontalAlign="center"
     width="100%" 
     height="100%">
  <s:CheckBox id="chk"
     click="chk_clickHandler(event)"/>
 </s:VGroup>
</s:GridItemRenderer>

CSS file for the application - ../css/style.css
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.customCheckBox{
 skinClass: ClassReference("skins.CustomCheckBoxSkin");
}
* Click here for the demo shown in this post.
  (Try changing some of the checkbox to reflect the change of state in the topmost
  checkbox.)
^ Click here for the source files for the demo.

Thursday, June 13, 2013

HTML: Background Colour with Opacity

Well, I was working the other day and one of my colleagues told me that the div that has a background colour with an opacity of 70 doesn't work in IE. After a bit of Googling and a bit of trial and error, I managed to get it working. (It works in Google Chrome, Mozilla Firefox, Internet Explorer 7, 8 and 9. However, the solution doesn't really work with Internet Explorer with different standards.)

Let's go through parts of the source codes first. The following liner will enforce your Internet Explorer 9 onwards to fall back and use Internet Explorer 8 standards. However, this will also caused all your Internet Explorer 9 codes to malfunction.
<meta http-equiv="X-UA-Compatible" content="IE=8" >
The following codes are meant for super old browsers that doesn't supports the css RGBa(3 primary colours and alpha).
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0) transparent;
The following codes are meant for super new browsers that supports the css RGBa(3 primary colours and alpha). (For example: latest Mozilla Firefox, Google Chrome, etc.)
/* RGBa with 0.7 opacity */
background: rgba(0, 0, 0, 0.7);
The following codes are meant for the older Internet Explorers. Would need to add the condition <!--[if lte IE 8]>, because browsers like Internet Explorer 9 will apply both filters and RGBa. =.=""
    <!--[if lte IE 8]>
        <style>
            #mainbg1 {
                /* For IE 5.5 - 7*/ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2000000, endColorstr=#b2000000);
                /* For IE 8*/
                -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2000000, endColorstr=#b2000000)";
            }
        </style>
    <![endif]-->
And here's all the source codes at one glance.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=8" >
    <title>Test</title>
    <style type="text/css" media="screen"> 
        body{
            margin: 0px;
			background-color:#00FF00;
		}
        #mainbg {
            width:100%; 
			height:1000px; 
			text-align:center; 
			position:absolute;
        }
        #mainbg1 {
            width:500px;
            height:500px;
            margin: 0px auto;
	
            /* Fallback for web browsers that doesn't support RGBa */
            background: rgb(0, 0, 0) transparent;
            /* RGBa with 0.7 opacity */
            background: rgba(0, 0, 0, 0.7);
        }
    </style>
    <!--[if lte IE 8]>
        <style>
            #mainbg1 {
                /* For IE 5.5 - 7*/ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2000000, endColorstr=#b2000000);
                /* For IE 8*/
                -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2000000, endColorstr=#b2000000)";
            }
        </style>
    <![endif]-->
</head>
<body>
<div id="mainbg">
    <div id="mainbg1">
    </div>
</div>
</body>
</html>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, February 23, 2013

JQuery: Irritating button gap...

I was working on Javascript and JQuery the other day and I have came across this strange button gap between a button set, which is kinda annoying. After spending some time playing around it, I finally could come up with a workaround for this annoying problem.

Main HTML file - index.html
<!doctype html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title>JQuery Buttons</title>
    <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.1/themes/base/jquery-ui.css">
 <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.jquery.com/ui/1.10.1/jquery-ui.js"></script>
 <link rel="stylesheet" href="css/index.css">
    <script src="js/index.js"></script>
</head>
<body>
 <section>
  <input name="grp0" type="radio" id="btn0" />
  <label for="btn0">Button 0</label>
  <input name="grp0" type="radio" id="btn1" />
  <label for="btn1">Button 1</label>
  <input name="grp0" type="radio" id="btn2" />
  <label for="btn2">Button 2</label>
  <input name="grp0" type="radio" id="btn3" />
  <label for="btn3">Button 3</label>
  <input name="grp0" type="radio" id="btn4" />
  <label for="btn4">Button 4</label>
  <input name="grp0" type="radio" id="btn5" />
  <label for="btn5">Button 5</label>
 </section>
 <section class="btns">
  <input name="grp1" type="radio" id="btns0" />
  <label for="btns0">Button 0</label>
  <input name="grp1" type="radio" id="btns1" />
  <label for="btns1">Button 1</label>
  <input name="grp1" type="radio" id="btns2" />
  <label for="btns2">Button 2</label>
  <input name="grp1" type="radio" id="btns3" />
  <label for="btns3">Button 3</label>
  <input name="grp1" type="radio" id="btns4" />
  <label for="btns4">Button 4</label>
  <input name="grp1" type="radio" id="btns5" />
  <label for="btns5">Button 5</label>
 </section>
</body>
</html>

Main CSS file - css/index.css (The magic is done here... :P)
@charset "utf-8";
/* CSS Document */

html,body{
 width:100%;
 height:100%;
 vertical-align:middle;
 text-align:center;
}

section{
 padding:2em;
}

.btns .ui-button{
    margin-left: 0;
    margin-right: -4px;
}

Main Javascript file - js/index.js
$( document ).ready(function() {
 $( "section input[type='radio']" )
  .button();
});// JavaScript Document
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, December 8, 2012

OMG it still exists....

Do you have experience creating a website? Spending too much time creating and debugging a website? And how much time have you spent on the debugging process? But do you know that IE6 still holds more than 5% of the overall market share for web browsers?


Image taken from 'NetMarketShare'.
According to the website shown in the above, more than 50% of the market
share are IE browsers. On top of that just by combining IE6, IE8 and IE9
still takes up more than 50% of the overall market share. And if you do
a search for the term 'IE6' in google, you will be getting all sorts of
results related to articles asking users to upgrade their browser to a better one.

Anyway the website doesn't provide statistics of the desktop browser alone.
There's statistics for the Operating System used by desktop users,
Operating System used by mobile, Search Engines, etc...
(I wonder when can we reach the day where IE6 would drop to less than 1%
in the overall market share for Web browsers. O.O)

* Click here to find out more about 'NetMarketShare'.

Sunday, November 20, 2011

Secret to display nicely formatted programming codes in your blogs/websites

If you have been following this blog for a short period of time, you probably would ask the question of how do I display programming codes in such a nicely formatted manner? I remembered the day that I had the same doubt as you do and there's a secret to it. Introducing... SyntaxHighlighter.


So what can SyntaxHighlighter do?
Click here for the demo of SyntaxHighlighter.

Isn't it interesting? On top of that, SyntaxHighlighter support programming language like as3, xml, php, C++, Javascript, etc... Isn't that nice?
Click here for a more precise list of programming language that SyntaxHighlighter supports.

So how do I configure it?
You just need to copy and paste the following codes into the <head> tag of your HTML Template of your blog.

<link href='http://alexgorbatchev.com/pub/sh/2.1.382/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/2.1.382/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shAutoloader.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shBrushAS3.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shBrushCss.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shBrushPhp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shBrushPlain.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/2.1.382/scripts/shBrushXml.js' type='text/javascript'/>
<script type='text/javascript'>
     SyntaxHighlighter.all()
</script>
</head>

and and a <pre> tage like the following example will do.
<pre class="brush: js">
    /**
     * SyntaxHighlighter
     */
    function foo()
    {
        if (counter <= 10)
            return;
        // it works!
    }
</pre>

Click here for a more detailed explanation on how to setup SyntaxHighlighter in your blog.