June 2011 - Posts

Web-Kit Transform3D , Translate, and Duration

I’ve got a sample case:

there is an existing jcarousel and overtime we’d like to support the touch and drag on IOS and android.called it swipe.

now how do you possibly do this without any framework like sencha touch or jqtouch?.

 

WebKit is unique amongst browser rendering engines in that it allows animation to be specified in pure CSS. Although this may never actually make it in to the CSS 3 specification, it degrades nicely.

everything relies on webkit capability of course you can do what ever rotate,etc

for this sample case ,the answer is on transform3D(x,y,z).

#mygridinsidecarousel
{
               -webkit-transition-property: -webkit-transform;
               -webkit-transition-duration: 0.5s;
               -webkit-transition-timing-function: ease-out;
               /*apply a transfor to kick in the hardware acceleration.  Without this, the first time we add the transform you get odd rendering of the divs (half missing) */
               -webkit-transform: translate3d(0px,0px,0px); 
 }

Set the jcarouse differently, no animation when going next. no extra left and right. they are going to swipe it anyway

if (isIOS() || isAndroid()) {
           jQuery('#mycarousel').jcarousel({
               scroll: 1,
               visible: 1,
               initCallback: mycarousel_initCallback,
                itemLoadCallback: mycarousel_itemLoadCallback,
               // This tells jCarousel NOT to autobuild prev/next buttons
               buttonNextHTML: null,
               buttonPrevHTML: null,
               //turn off for ios so no extra sliding
               animation:0
           });
var swipeOptions =
          {
              triggerOnTouchEnd: true,
              swipeStatus: swipeStatus,
              threshold: 100
          }
 
          $(function () {
              $("#mycarousel .jcarousel-clip-horizontal").css('border', '1px solid black');
              $("#mycarousel .jcarousel-clip-horizontal").css('-webkit-border-radius', '10px');
 
              $("#mycarousel").css('overflow', 'hidden');
              $("#mycarousel").css('position', 'relative');
              imgs = $("#mycarousel .jcarousel-clip-horizontal");
              imgs.swipe(swipeOptions);
          });

Reduce threshold, to make how far Drag is consider as a Swipe

//Swipe handlers
    function swipeStatus(event, phase, direction, distance) {
        //If we are moving before swipe, and we are going Lor R in X mode, or U or D in Y mode then drag.
        if (phase == "move" && (direction == "left" || direction == "right")) {
            var duration = 0;
 
            if (direction == "left")
                scrollImages((IMG_WIDTH * currentImg) + distance, duration);
 
            else if (direction == "right")
                scrollImages((IMG_WIDTH * currentImg) - distance, duration);
 
        }
 
        else if (phase == "cancel") {
            //scrollImages(IMG_WIDTH * currentImg, speed);
            reset();
        }
 
        else if (phase == "end") {
        //alert('end:'+distance+",dir"+direction);
            if (direction == "right")
                previousImage()
            else if (direction == "left")
                nextImage()
        }
    }
 
 
 
    function previousImage() {
 
        if (prevBtn == 1) {
           // alert('load prev');
            reset();
            myCarousel.prev();
        }
        return false;
 
    }
    function reset() {
        //imgs.css("left",  "0px");
        imgs.css("-webkit-transform", "");
    }
    function nextImage() {
       
        if (nextBtn == 1) {
 
            reset();
            myCarousel.next();
 
    }
      

There you have it a carousel that swipe on IOS Open-mouthed smile, cheers

Plugin Used

Of course you can find that it can do more fancy than this, just google and you’ll find fancy animation far beyond this.

this is just sample case

Updated 2011-06-28

For more natural effect, i don’t use carousel for Ios and android. i use the same as the example on the plugin example.

load all pages using settimeout and load all append to the right, create a viewport of carousel with overflow hidden.

and than just use the swipe as usual.

Share this post: | | | |
Posted by cipto with no comments

Domain Driven Design Part 3

Just got back to this. I’m thinking about my project and now I’d like to split it into several BC(Bounded Context)s.

on my case:

“the way of ordering is different when there is a bundle package(a marketing bundle for products with discount)

or Ordinary package. this change the way application work.” so order has become different meaning for BundleContext and OrderContext. and all other product descandent.

also I’ve got other users type which the interest is not on ordering, and it’s like admin side. this also need to be seperated, as this will treat product user in different meaning

.another suggestion would be to separate the users Identity and Role into another context. that way the other context would only Know that UserRole/Type Class .

now for communication : each context has it’s own Service exposed to other context.it has API to Translate it to the local domain (ACL).

our API has it’s own contract and language (could be XML or directly byte on the messaging). the service host could be HTTP or TCP.

you need also to define wether it is upstream or downstream.

it can be hosted on WCF Services (http or tcp), or if it has caching inside of that context use NBUS event Driven. so you could message “Someting is New” and told other context “Reload that Cache”

in my case i don’t really work in separate application, except the admin site that could tell the current web cache, “Hey i’ve add new product ,please get the latest one”

so somehow I’ll add that service to ordercontext. and the admin application will call that service.

i do like the Notification that can go back and forth

as for Shared Kernel, since it’s like a Model shared among context or Team of development. I’d say just a class library which is reference by both context.

Still a bit confuse and I’m sure I’m almost there.

Related Article:

http://blog.scottmfelder.com/tag/ddd/

http://www.infoq.com/articles/ddd-contextmapping

Aggregate Root is the key for publishing event. you should read more about Domain Event

 

Ah found a great book. for this i skip to chapter 3.

Professional Asp.net Design Pattern

Share this post: | | | |
Posted by cipto with no comments

Streaming for Apple iPhone/Ipad

Finally got this working.You’ve got that right ,Lack of Documentation

“Apple iPhone uses HTTP byte-ranges for requesting audio and video files. First, the Safari Web Browser requests the content, and if it's an audio or video file it opens it's media player. The media player then requests the first 2 bytes of the content, to ensure that the Webserver supports byte-range requests. Then, if it supports them, the iPhone's media player requests the rest of the content by byte-ranges and plays it.” Detail

So at first time IOS device will request byte 0-1 to see if it can accept the partial/chunk streaming.

if successful it will request for the whole content, or partial content. everything is on HTTP_Range server value during the HttpRequest,Patter: Start-End ex (0-1,0-41299).

with proper encoding of the video it will run, note: this code only support single range, not multiple.

it’s all on PHP and I’ve convert it to Asp.net. enjoy

   1: using System;
   2: using System.Web;
   3: using System.IO;
   4: using System.Collections.Generic;
   5: /// <summary>
   6: /// Support Single Range Request Only
   7: /// </summary>
   8: public class VideoStreamer : IHttpHandler {
   9:     
  10:     private void RangeDownload(string fullpath,HttpContext context)
  11:     {
  12:         long size,start,end,length,fp=0;
  13:         using (StreamReader reader = new StreamReader(fullpath))
  14:         {
  15:            
  16:             size = reader.BaseStream.Length;       
  17:             start = 0;
  18:             end = size - 1;
  19:             length = size;
  20:             // Now that we've gotten so far without errors we send the accept range header
  21:             /* At the moment we only support single ranges.
  22:              * Multiple ranges requires some more work to ensure it works correctly
  23:              * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
  24:              *
  25:              * Multirange support annouces itself with:
  26:              * header('Accept-Ranges: bytes');
  27:              *
  28:              * Multirange content must be sent with multipart/byteranges mediatype,
  29:              * (mediatype = mimetype)
  30:              * as well as a boundry header to indicate the various chunks of data.
  31:              */
  32:             context.Response.AddHeader("Accept-Ranges", "0-" + size);
  33:             // header('Accept-Ranges: bytes');
  34:             // multipart/byteranges
  35:             // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
  36:     
  37:             if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"]))
  38:             {
  39:                 long anotherStart = start;
  40:                 long anotherEnd = end;
  41:                 string[] arr_split = context.Request.ServerVariables["HTTP_RANGE"].Split(new char[] { Convert.ToChar("=") });
  42:                 string range = arr_split[1];
  43:  
  44:                 // Make sure the client hasn't sent us a multibyte range
  45:                 if (range.IndexOf(",") > -1)
  46:                 {
  47:                     // (?) Shoud this be issued here, or should the first
  48:                     // range be used? Or should the header be ignored and
  49:                     // we output the whole content?
  50:                     context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
  51:                     throw new HttpException(416, "Requested Range Not Satisfiable");
  52:  
  53:                 }
  54:  
  55:                 // If the range starts with an '-' we start from the beginning
  56:                 // If not, we forward the file pointer
  57:                 // And make sure to get the end byte if spesified
  58:                 if (range.StartsWith("-"))
  59:                 {
  60:                     // The n-number of the last bytes is requested
  61:                     anotherStart = size - Convert.ToInt64(range.Substring(1));
  62:                 }
  63:                 else
  64:                 {
  65:                     arr_split = range.Split(new char[] { Convert.ToChar("-") });
  66:                     anotherStart = Convert.ToInt64(arr_split[0]);
  67:                     long temp = 0;
  68:                     anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) ? Convert.ToInt64(arr_split[1]) : size;
  69:                 }
  70:                 /* Check the range and make sure it's treated according to the specs.
  71:                  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
  72:                  */
  73:                 // End bytes can not be larger than $end.
  74:                 anotherEnd = (anotherEnd > end) ? end : anotherEnd;
  75:                 // Validate the requested range and return an error if it's not correct.
  76:                 if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size)
  77:                 {
  78:  
  79:                     context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
  80:                     throw new HttpException(416, "Requested Range Not Satisfiable");
  81:                 }
  82:                 start = anotherStart;
  83:                 end = anotherEnd;
  84:  
  85:                 length = end - start + 1; // Calculate new content length
  86:                 fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
  87:                 context.Response.StatusCode = 206;
  88:             }
  89:         }
  90:             // Notify the client the byte range we'll be outputting
  91:         context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
  92:         context.Response.AddHeader("Content-Length", length.ToString());
  93:             // Start buffered download
  94:             context.Response.WriteFile(fullpath, fp, length);
  95:             context.Response.End();
  96:          
  97:     }
  98:  
  99:     public void ProcessRequest(HttpContext context)
 100:     {
 101:         //context.Response.Headers.Clear();
 102:         string filename = context.Request["fn"];
 103:         string mimetype = "video/mp4";
 104:         string fullpath=context.Server.MapPath("video/output/"+filename);        
 105:         if (System.IO.File.Exists(fullpath))
 106:         {
 107:             
 108:             context.Response.ContentType = mimetype;
 109:             if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"]))
 110:             {
 111:                 //request for chunk
 112:                 RangeDownload(fullpath,context);
 113:             }
 114:             else
 115:             { 
 116:                 //ask for all 
 117:                     long fileLength = File.OpenRead(fullpath).Length;
 118:                     context.Response.AddHeader("Content-Length", fileLength.ToString());
 119:                     context.Response.WriteFile(fullpath);             
 120:                 
 121:                 
 122:             }
 123:         }
 124:         else
 125:         {
 126:             throw new HttpException(404, "Video Not Found Path:"+fullpath);
 127:         }
 128:     }
 129:  
 130:     public bool IsReusable {
 131:         get {
 132:             return false;
 133:         }
 134:     }
 135:  
 136: }

 

You can than use it on your html 5 video tag.

   1: <video width="340" height="285" id="htmlvidplayer" controls="" poster="/video/output/53_big.jpg" tabindex="0">
   2: <source id="mp4" src="services/VideoStreamer.ashx?fn=/video/output/53.mp4" type="video/mp4">
   3: </source>
   4: </video>

or directly Redirect to that url, because the devices have those built in quicktime player.

   1: <a href="services/VideoStreamer.ashx?fn=/video/output/53.mp4>
   2: <img src="video/output/53_big.jpg"/>
   3: </a>

Related to how to build Cross browser video. well in my case it's only IOS use HTML5 or Desktop Browser use flash.
this is the Javascript Example:

   1: function LoadMediaPlayer(fileName, thumbnailPic) {
   2:     var videocontainerid='mediaplayer';
   3:     var x = document.getElementById('htmlvidplayer');
   4:     if(x)
   5:     document.getElementById(videocontainerid).removeChild(x);
   6:     if (!isIOS() && !isAndroid()) {
   7:     var so = new SWFObject("../mplayer/TFMP13.swf", "mediaplayer", "480", "345", "8", "#000000");
   8:     so.addParam("allowFullScreen", "false");
   9:     so.addVariable("MediaLink", fileName);
  10:     so.addVariable("image", thumbnailPic); // preview image
  11:     so.addVariable("imageScaleType", "1");
  12:     so.addVariable("logo", "../images/tf_logo_small.png"); // logo image file
  13:     so.addVariable("logoLink", "http://www.something.com"); // when logo is clicke
  14:     so.addVariable("logoTarget", "_blank"); // target frame when logo is clicked
  15:     so.addVariable("playOnStart", "false");
  16:     so.addVariable("startVolume", "50"); // 0-100
  17:     so.write(videocontainerid);
  18:     }
  19:     
  20: else {
  21:     //use video tag
  22:     fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
  23:     var v = document.createElement("video");
  24:     v.id = 'htmlvidplayer';
  25:     v.width = '480';
  26:     v.height = '345';
  27:     v.controls = true;
  28:     v.poster = thumbnailPic;
  29:     var mp4 = document.createElement('source');
  30:     mp4.id = 'mp4'; mp4.src = '/services/VideoStreamer.ashx?fn=' + fileName; mp4.type = 'video/mp4';
  31:     v.appendChild(mp4);
  32:     
  33:     var g = document.getElementById(videocontainerid);
  34:     g.appendChild(v);
  35:     }
  36:  }

It’s Hosted on Codeplex

Share this post: | | | |
Posted by cipto with no comments

Smooth Streaming MP4 for IOS Devices (Iphone,Ipad)

After a lot digging on this. a bit confuse at first. but finally almost comes to conclusion.

so in order to have it play able,you have to have the correct encoding and proper streaming it.

if you just want it to be playable the file must act like downloaded not streamed, but apple has restriction on the file size though.

the proper way is to stream it. there are http module from code-shop for free which in combination with mp4 utility, and ffmpeg.

and we have alternative product built in for asp.net , SmoothStream which use the Microsoft Encoder for encoding the proper one, Detail.

we must create the necessary files

Server manifest files (.ism)

Client Manifest files

and properly direct/handle the request for ism,ismc,ismv,m3u8 (play list)

Share this post: | | | |
Posted by cipto with no comments

Glimpse a server side Firebug

Have just got back to my mvc 3 project. after research on how to build unobtrusive Javascript with MVC, on the way i found about this.

1 word , awesome.

when you are debugging your project and you would like to output your server side to browser

some operation like Trace.Write , Ajax Call, Debug Routing, just use this . all in 1.

so when you press F5, and than go to this URL : http://localhost/Glimpse/Config click Turn Glimpse On.

 

browse through your page,you gonna have that button with an eye , click on it. There you have all the output

image

 

Share this post: | | | |
Posted by cipto with no comments