What I did in 2012? A review

For the sake of fun and keeping record; I'm sharing today "How I spent the year 2012!".

I developed many programming tools; experimented many new technologies like WebRTC as well as Canvas2D; developed many big private/public projects.

HTML Canvas Designer / try yourself
Canvas Designer is a drawing-tool which lets you draw any shape on a single drawing-surface; also it auto-generates appropriate Canvas 2D API relevant code for you in relative/absolute shortened/unshortened formats!
I designed it in 15-to-20 days....in May 2012.

HTML Curvature / try yourself
Curvature is a designer/tool for curving. It generates Canvas2D APIs relevant code in relative/absolute shortened/unshortened formats! It gives you full control over Bezier curves.
It was my first tool in 2012. I started working on it from 1st January; and I release it at 16 January 2012.

WebRTC Experiments & Demos / try yourself
In the last quarter of 2012; I started experimenting RTCWeb APIs. I did many realtime experiments:

---) WebRTC Text Broadcast / Chat using RTCDataChannel APIs
---) WebRTC File Broadcast / Sharing Files using RTCDataChannel APIs

1) WebRTC Screen Broadcasting!
WebRTC screen broadcasting: using Google Chrome experimental tabCapture APIs to broadcast screen over many peers.

2) WebRTC Video Broadcasting!
Allows you broadcast your video privately or publicly over many peers.

3) WebRTC Audio Broadcasting!
Allows you broadcast your voice privately or publicly over many peers.

4) WebRTC Experiment using WebSocket!
5) WebRTC Experiment using Pubnub!
6) WebRTC Experiment using socket.io!
7) WebRTC Experiment using XHR and ASP.NET MVC!

and there are many others. You can see all of them here.

HTML Canvas2D Experiments / try yourself
I experimented Canvas2D from June to August.

1) Bezier Curves and Coloring    1 . 2 . 3 . 4 . 5 . 6 . 7 . 8
2) Dragging/Moving shapes smoothly using Canvas 2d APIs
3) Flying Bird Experiment
4) Rocket Fire Experiment
5) Many Canvas2D Sketches

I tried CSS3 too!

Elance / view my elance profile
I started working on elance projects from 14th August 2012. Since then I got upto 30 unique clients from different areas of the world! It was a fun! Majority of projects were direct (and private); so you can't see them in the list.

There were some challenging projects for me. I’m a little bit crazy when I accept challenge. I can’t stop trying until I get success. For a project, I tried so many times I can’t remember; but I got success at the end!


UseMe: A comparative way of HTML5 features detection / try yourself


Just a fun!

Taxicab / work in progress
It is an online taxicab dispatching and booking as well as management system...it has following features:
1) An advance online booking system (anyone can book cars)
2) Some unique discounts and offers
3) An advance fares management system
4) Admin panel: manages the whole project
5) Operator panel: dispatches bookings and there are so many other features in this panel
6) An advance search
7) Postcodes database: around 2 million records in that database!!

and there are so many other things.
You can see my old taxicab projects (that I developed in 2010) in the apps section below.

Apps / try yourself
You can see all my apps here:


Dashing Quill Blog / another blog
I started this blog in 2011. In 2012, upto 7,600 unique people visited:

Click here to see full report of the year 2012 for Dashing Quill Blog
You can see what I posted there in 2012 here.

Most famous posts were:
1) Capturing WebCam using DirectShow.NET Library - Link
2) Javascript and CSS3 only sliding up/down transition effects - Link
3) Handling errors in ASP.NET MVC - Link

Google Sites / another blog
I posted two most famous articles in this blog...

1) ASP.NET MVC security and hacking: Defense-in-depth - Link
2) JavaScript Logical Operators: An Overview - Link

Note:
Upto 24655 unique people visited this blog in 2012.

The most famous posts were:
1) Absolute or Relative URL issues and the solution
2) Exploring CSP (Content Security Policy) using ASP.NET MVC
3) C# and wiki markup parsing

DTweet / an open source ASP.NET MVC project
It is an open source project. I developed it in 2011 and released in 2012.

In 2012, I started my career as open-source web developer. 2013 is coming with great opportunities.

I’m ready to do better! 

Save files on disk using JavaScript or JQuery!

You can save any file, or DataURL, or Blob on disk using HTML5's newly introduced "download" attribute.

Use cases:

1. Force browser to download/save files like PDF/HTML/PHP/ASPX/JS/CSS/etc. on disk
2. Concatenate all transmitted blobs and save them as file on disk - it is useful in file sharing applications

Microsoft Edge? (msSaveBlob/msSaveOrOpenBlob) https://msdn.microsoft.com/en-us/library/hh779016(v=vs.85).aspx

/**
 * @param {Blob} file - File or Blob object. This parameter is required.
 * @param {string} fileName - Optional file name e.g. "image.png"
 */
function invokeSaveAsDialog(file, fileName) {
    if (!file) {
        throw 'Blob object is required.';
    }

    if (!file.type) {
        file.type = 'video/webm';
    }

    var fileExtension = file.type.split('/')[1];

    if (fileName && fileName.indexOf('.') !== -1) {
        var splitted = fileName.split('.');
        fileName = splitted[0];
        fileExtension = splitted[1];
    }

    var fileFullName = (fileName || (Math.round(Math.random() * 9999999999) + 888888888)) + '.' + fileExtension;

    if (typeof navigator.msSaveOrOpenBlob !== 'undefined') {
        return navigator.msSaveOrOpenBlob(file, fileFullName);
    } else if (typeof navigator.msSaveBlob !== 'undefined') {
        return navigator.msSaveBlob(file, fileFullName);
    }

    var hyperlink = document.createElement('a');
    hyperlink.href = URL.createObjectURL(file);
    hyperlink.target = '_blank';
    hyperlink.download = fileFullName;

    if (!!navigator.mozGetUserMedia) {
        hyperlink.onclick = function() {
            (document.body || document.documentElement).removeChild(hyperlink);
        };
        (document.body || document.documentElement).appendChild(hyperlink);
    }

    var evt = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
    });

    hyperlink.dispatchEvent(evt);

    if (!navigator.mozGetUserMedia) {
        URL.revokeObjectURL(hyperlink.href);
    }
}

Here is how to use above function:

var textFile = new Blob(['Hello Sir'], {
   type: 'text/plain'
});
invokeSaveAsDialog(textFile, 'TextFile.txt');

You can pass two arguments over "SaveToDisk" function:

1. file-URL or blob or data-URL - it is mandatory
2. file name - it is optional

Here is "SaveToDisk" function uses new syntax of "createEvent" API:

function SaveToDisk(fileURL, fileName) {
    // for non-IE
    if (!window.ActiveXObject) {
        var save = document.createElement('a');
        save.href = fileURL;
        save.target = '_blank';
        save.download = fileName || 'unknown';

        var event = document.createEvent('Event');
        event.initEvent('click', true, true);
        save.dispatchEvent(event);
        (window.URL || window.webkitURL).revokeObjectURL(save.href);
    }

    // for IE
    else if ( !! window.ActiveXObject && document.execCommand)     {
        var _window = window.open(fileURL, '_blank');
        _window.document.close();
        _window.document.execCommand('SaveAs', true, fileName || fileURL)
        _window.close();
    }
}

Here is "SaveToDisk" function uses old syntax of "createEvent" API:

function SaveToDisk(fileURL, fileName) {
    // for non-IE
    if (!window.ActiveXObject) {
        var save = document.createElement('a');
        save.href = fileURL;
        save.target = '_blank';
        save.download = fileName || fileURL;
        var evt = document.createEvent('MouseEvents');
        evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0,
            false, false, false, false, 0, null);
        save.dispatchEvent(evt);
        (window.URL || window.webkitURL).revokeObjectURL(save.href);
    }

    // for IE
    else if ( !! window.ActiveXObject && document.execCommand)     {
        var _window = window.open(fileURL, "_blank");
        _window.document.close();
        _window.document.execCommand('SaveAs', true, fileName || fileURL)
        _window.close();
    }
}

You can save blobs too; on disk:

function SaveToDisk(blobURL, fileName) {
    var reader = new FileReader();
    reader.readAsDataURL(blobURL);
    reader.onload = function (event) {
        var save = document.createElement('a');
        save.href = event.target.result;
        save.target = '_blank';
        save.download = fileName || 'unknown file';

        var event = document.createEvent('Event');
        event.initEvent('click', true, true);
        save.dispatchEvent(event);
        (window.URL || window.webkitURL).revokeObjectURL(save.href);
    };
}

Using "SaveToDisk" function

Force an image to be saved on disk instead of rendered by the browser:

SaveToDisk('https://muazkh.appspot.com/images/Curvature.PNG', 'image.png');

Force downloading of pdf files (it will NEVER allow any browser specific pdf-reader to render/open your pdf files):

SaveToDisk('https://muazkh.googlecode.com/files/Muaz-Khan-CV.pdf');

Even you can enforce following web-browser specific files to be downloaded/saved on the disk instead of rendered within the browser!

JavaScript SaveToDisk('/javascript-file.js')
HTML SaveToDisk('/html-file.html')
CSS SaveToDisk('/css-file.css')
ASPX SaveToDisk('/aspx-file.aspx')
PHP SaveToDisk('/php-file.php')
MVC SaveToDisk('/controller/action-method')

Following apps are using "SaveToDisk" function to save files/blobs/etc. on disk:

DataChannel.js A library for realtime data/file sharing using WebRTC!
RTCMultiConnection.js A library for realtime audio/video/screen/data and file sharing using WebRTC!
Group File Sharing Sharing files over multiple peer connections concurrently
RecordRTC A library for WebRTC-Developers to record audio and video streams

Specification

1. https://developer.mozilla.org/en-US/docs/DOM/document.createEvent
2. http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-DocumentEvent-createEvent

function SaveToDisk(fileUrl, fileName) {
    var hyperlink = document.createElement('a');
    hyperlink.href = fileUrl;
    hyperlink.target = '_blank';
    hyperlink.download = fileName || fileUrl;

    var mouseEvent = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
    });

    hyperlink.dispatchEvent(mouseEvent);
    (window.URL || window.webkitURL).revokeObjectURL(hyperlink.href);
}


Remember, "SaveToDisk" works fine on Firefox nightly and aurora.

To support Firefox general release; use same workaround that is used for IE in this post (with a little bit changes).

If Firefox fails:

It seems that firefox doesn't allows dispatching (click) event handlers if HYPER-LINK element is NOT in the DOM-tree.

Don't call "revokeObjectURL" outside the "onclick" handler.

You simply need to append HYPER-LINK element  into DOM; and remove it after "onclick" is fired:

function SaveToDisk(fileUrl, fileName) {
    var hyperlink = document.createElement('a');
    hyperlink.href = fileUrl;
    hyperlink.target = '_blank';
    hyperlink.download = fileName || fileUrl;

    (document.body || document.documentElement).appendChild(hyperlink);
    hyperlink.onclick = function() {
       (document.body || document.documentElement).removeChild(hyperlink);
    };

    var mouseEvent = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
    });

    hyperlink.dispatchEvent(mouseEvent);
    
    // NEVER use "revoeObjectURL" here
    // you can use it inside "onclick" handler, though.
    // (window.URL || window.webkitURL).revokeObjectURL(hyperlink.href);

    // if you're writing cross-browser function:
    if(!navigator.mozGetUserMedia) { // i.e. if it is NOT Firefox
       window.URL.revokeObjectURL(hyperlink.href);
    }
}

Exploring CSP (Content Security Policy) using ASP.NET MVC

In this post, I'll practically show you one promising new defense using CSP (Content Security Policy) that can significantly reduce possible XSS (Cross-Site Scripting) attacks in modern web-browsers (currently Chrome 16+ and Firefox 4+)!

I'll not only block inline/outer scripts but also ask user-agent to auto-generate report for each violated activity it founds that violates my pre-defined policy.

I created an ASP.NET MVC demo app; which is aimed to:
  1. Attach HTTP headers for CSP with each response
  2. Save and preview all reports generated by the browser
                      Download Demo Project


Here is how Google Chrome blocks unallowed scripts:



And the Firefox is blocking unallowed scripts as well:


Here is how Google Chrome generates a report to pre-defined 'report-uri' directive and passes data as 'application/json':



To append CSP headers for each response; we'll add code in "Application_BeginRequest" method in "MvcApplication" class under "Global.asax" file:

void Application_BeginRequest(object sender, EventArgs ex)
{
    /* ======== For Chrome ======== */
    Response.AddHeader("X-WebKit-CSP", "default-src 'self'; img-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; report-uri /Home/Report");

    /* ======== For Firefox ======== */
    Response.AddHeader("X-Content-Security-Policy", "default-src 'self'; img-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; report-uri /Home/Report");
}


As you can see in the above code, I used following two headers for CSP implementation:
  1. "X-Content-Security-Policy" for Firefox
  2. "X-WebKit-CSP" for Chrome
I used 'report-uri' directive to instruct the browser to notify me about any activity that violates my pre-defined policies.

... report-uri /Home/Report

The "Report" action method looks like this:

public JsonResult Report() { return Json(true); }

Remember, POST/GET doesn't matter for this action method! Also the browser will totally ignore what you return with this action. Because: "User Agents MUST NOT honor HTTP 3xx response codes to prevent HTTP header leakage across domains."


I'm blocking all inline as well as outer scripts for possible security gain; however I'm allowing inline-styles because it is difficult for me to not use inline-styles!!!

...; script-src 'self'; style-src 'self' 'unsafe-inline'; ...

"Banning inline script is the biggest security win CSP provides, and banning inline style likewise hardens your application."


To allow all outer scripts from SSL:

script-src https:

To allow inline scripts as well:

script-src https: 'unsafe-inline'

Instead of blocking any resource; you can use report-only header to ONLY get notified of violated activities:

/* ======== For Chrome ======== */
Response.AddHeader("X-WebKit-CSP-Report-Only", "...; report-uri /Home/Report");

/* ======== For Firefox ======== */
Response.AddHeader("X-Content-Security-Policy-Report-Only", "...; report-uri /Home/Report");

"The policy specified in report-only mode won't block restricted resources, but it will send violation reports to the location you specify."



img-src *

I'm also allowing images from all locations (http/https) by using asterisk (*) symbol. To restrict SSL only domains for images:

img-src https: *

Or to allow self-domain ONLY for images:

img-src 'self'

There as so many other directives that you can use to get full control over content that was not possible yesterday. For example, you can use:

  1. connect-src
    Limits the origins to which you can connect (via XHR, WebSockets, and EventSource).

  2. font-src
    Pecifies the origins that can serve web fonts. Google's Web Fonts could be enabled via font-src https://themes.googleusercontent.com

  3. frame-src
    Lists the origins that can be embedded as frames. For example: frame-src https://youtube.com would enable embedding YouTube videos, but no other origins.

  4. media-src
    Restricts the origins allowed to deliver video and audio.

  5. object-src
    Allows control over Flash and other plugins.

Firefox's Behavior regarding CSP

Firefox fails to recognize/parse 'unsafe-inline' source as show in the following figure:

Firefox not only displays CSP Error but also CSP Warning:

CSP ERROR: Couldn't parse invalid source 'unsafe-inline'
CSP WARN: Failed to parse unrecoginzied source 'unsafe-inline'

Firefox is also NOT appending 'document-uri' directive in the report.

Firefox absolute-links the 'blocked-uri' however Google Chrome just appends the origin only.

For "inline script base restriction"; Firefox uses 'self' as 'blocked-uri' value however Google Chrome ignores it.

For further reading:
  1. http://www.w3.org/TR/CSP/
  2. https://wiki.mozilla.org/Security/CSP/Specification
  3. http://www.html5rocks.com/en/tutorials/security/content-security-policy/
Updated at: Jan 15, 2012

Unprefixed support for Content Security Policy in Chrome 25 Beta
Content Security Policy (CSP) helps you reduce the risk of cross-site scripting and other content injection attacks. Starting in today’s Beta release, you can use the unprefixed Content-Security-Policy HTTP header to define a whitelist of trusted content sources. The browser will only execute or render resources from those sources. For example:

Using BackgroundWorker in Windows Forms Application

I created a simple Windows Forms project using C# while taking advantage of BackgroundWorker object to run task at backward thread.

You just have to change/alter only one method: "CallMeBackward" which is called at backward thread in the demo project.



using System;
using System.ComponentModel;
using System.Threading;

namespace BackgroundWorkerInWindowsFormsApp
{
    public partial class Form1 : System.Windows.Forms.Form
    {
        BackgroundWorker _backgroundWorker = new BackgroundWorker();
        
        /*============================================================================*/
        public Form1()
        {
            InitializeComponent();
            
            /*============================================================================*/
            _backgroundWorker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWorkEvent);
            _backgroundWorker.WorkerSupportsCancellation = true;

            ThreadPool.QueueUserWorkItem(_backgroundWorker.RunWorkerAsync);
            /*============================================================================*/
        }

        /*============================================================================*/
        void BackgroundWorkerDoWorkEvent(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker backgroundWorker = sender as BackgroundWorker;
            string argument = (string)e.Argument;
            e.Result = OnTimeConsumingOperation(backgroundWorker, argument);
        }
        /*============================================================================*/
        string OnTimeConsumingOperation(BackgroundWorker bw, string arg)
        {
            ThreadPool.QueueUserWorkItem(_ =>
            {
                CallMeBackward();
            });
            return string.Empty;
        }
        /*============================================================================*/
        void CallMeBackward()
        {
            for (var i = 0; i < 2000; i++)
            {
                counterLabel.Text = i.ToString();
                timerLabel.Text = DateTime.Now.ToLongTimeString();
            }
        }
        /*============================================================================*/
        protected override void Dispose(bool disposing)
        {
            _backgroundWorker.CancelAsync();
            _backgroundWorker.Dispose();
            /*============================================================================*/
            var timer = new System.Windows.Forms.Timer();
            timer.Tick += (obj, evt) =>
            {
                if (!_backgroundWorker.IsBusy)
                {
                    if (disposing && (components != null))
                    {
                        components.Dispose();
                    }
                    base.Dispose(disposing);
                }
            };
            timer.Start();            
        }

        /*============================================================================*/        
    }
}

UI elements are not thread-safe and should be accessed only on the thread that created them. Otherwise you'll get following error message:

Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.

BackgroundWorker cannot intercept main thread for UI elements. You've to use main thread instead.

Released Canvas Designer


Canvas Designer



A tool aimed to give you a full-fledged drawing surface and also auto generate appropriate code for you in different formats!

It targets Canvas 2D Context – i.e. it gives you a built-in IDE for Canvas 2D APIs!

Try the tool:
https://canvas-designer.appspot.com/

Introduction video:
Introducing Canvas Designer

Want to contribute or go in-depth:
http://muaz-khan.github.com/Everything/Canvas/Tools/Designer/Help/

Supported features:
Bezier and quadratic curves, arc (circles!), lines, rectangles, fill/stroke styles, line width/cap/join, global alpha and other properties.

Some funny simple sketches:
http://muaz-khan.github.com/Everything/Canvas/Sketches/

Flying Bird [work-in-progress!] (Experiment):
http://muaz-khan.github.com/Everything/Canvas/Experiments/Flying-Bird/

How I use CSS?

In this article, I am going to explorer how I use CSS – i.e. my way of using CSS – or how I design using CSS?

I prefer classes over tags and IDs.

.class-name { }

It doesn't mean that I don't use <tags> and #ids – I use them when appropriate!

My CSS classes are lowercase, hyphen-separated:

.header-top
.header-h1
.red-background
.skew-90deg

I always place repeated code in a separate class, and use it on demand. In future, I don't have to change CSS anymore; I just have to edit HTML class attributes:

.red-background { }

<span class="red-background">go ahead</span>
<div class="allow-select red-background">Long DIV selectable</div>
<a class="skew-90 rotate-180 red-background">Login</a>

Above code is much better than using comma separated selectors in CSS, in my opinion!

I never use !important in my code, trust me, never!

I don't use !important because it overrides previous styles and whenever I've to override any previous style; I place overridden code at the bottom of the CSS file without using !important - so everything works fine for me!

!important NEVER allow upcoming code to override it until you explicitly use !important in the later code! That's why I never use it.

For the sake of clarity and simplicity, I always order CSS selectors according to HTML elements priority.

(ORDER OF CSS SELECTORS)
html, body        top most priority
header, h1        second priority
menu              third priority
.content          fourth priority
footer            last priority (+media queries etc.)

This makes me comfortable regarding my CSS and I feel no confusion in later edits.

I use child, attribute and sibling selectors often without concerning IE6! - It is progressively enhanced way of using CSS!

For example see this code:

footer ~ * {
 display: none !important;
}

If someone dynamically appends HTML code at my page! I'll hide his HTML; however if he uses !important himself; there is no solution to hide his HTML!! – Remember this is the only place where I use !important. (Note: I use CSP [Content Security Policy] for inline/out-line CSS/JS protection; however it is still in draft! )

I never like default styles; so I always override them.

I use :after and :before pseudo selectors in the way that my layout also looks great in old browsers like IE6.

li:before {
 content: "-";
 margin-right: 5px;
}

IE6 will ignore it, and margins will NEVER apply.

I use negative margins too - IE6 is still stupid for this!

.dialog-box {
 margin-top: -20px;
}

There are a lot other alternatives for negative margins (float, text/word wrapping etc.); but I don't know why I always use negative margins! – It is easy to use and gives control over stuff! (Note: display: inline-block is not an alternative for negative margins!) [Well, clearfixing is also helpful for old IE]

For anchors (<a>), I use border-bottom instead of text-decoration – it looks great!

a {
 text-decoration: none;
 border-bottom: 1px solid blue;
 padding-bottom: 3px;
}

You may know that CSS values' order doesn't matter; however I always follow standard (common) style. As you can see the value of border-bottom; this is most common style on the web!

Negative text-indent is better for hiding text over images – I use it when needed:

.menu-button {
 background-image: url(about.png);
 text-indent: -111111px;
}

I use position:absolute often! - sometimes I also use position:fixed - however I strongly care IE6 in that case!

.fix-position {
 position: fixed;
 *position: absolute;  /* IE6 Hack */
}

I never used visibility:hidden - I use display:none instead. I know display: none causes reflow but I still use it!

I use line-height in unit-less format:

p, p {
 line-height: 1.5;
}
It inherits value from font-size.

In case when CSS value is zero; I use zero units-less!

When editing CSS within JavaScript; I use display:'' for allowing elements get their default display value.

header.style.display = '';

I love well-decorated code and I love using Unicode special characters to decorate and clarify my code!


There are many other tricks too – This is how I use CSS – Are you have any question, suggestion etc.?

Absolute or Relative URL issues and the solution


This article demonstrates the issues occur due to the usage of relative URLs while shifting pages from one location to another or the misuse of relative URLs and how to overcome those issues.

Relative URLs examples:
/* HTML example */
<img src="image.jpg" />


/* CSS example */
.image-div
{
    background-image: url(image.jpg);
}

/* JavaScript example */
image.src = 'image.jpg';

Relative URLs and expected issues
In simple words, relative URL reference link on the same server (or domain).
  • <img src="image.jpg" /> Reference of a resource from same directory

  • <img src="../../image.jpg" /> In CSS/HTML, ../ used to reference parent directory. In the above example, ../ is used two times; so it is referencing a resource from 2-level parent directory.

  • <img src="sub-directory/image.jpg" />
    Reference of a resource from sub directory
The issue occurs when when shifting a page from one location to another which cause broken links.

/ and ../ are two different things:
  • <img src="/image.jpg" />
    Reference of a resource from root directory
  • <img src="../image.jpg" />
    Reference of a resource from 1-level parent directory

  • <img src="image.jpg" />
    Reference of a resource from same directory
Absolute URLs: The solution or ...
Absolute URLs solves most of relative URLs issues and also helps prioritized your website (SEO!). Absolute URLs also help testers or late-viewers to understand (+access) the located resource easily.

In JavaScript, we can create a global variable to store domain (root) URL:

/* Global variable */
var domainName = location.protocol + '//' + location.host;

/* Usage */
image.src = domainName + '/image.jpg';

JAMES PADOLSEY way of getting a fully qualified (absolute) URL in JavaScript:

function qualifyURL(url) {
    var img = document.createElement('img');
    img.src = url; // set string url
    url = img.src; // get qualified/absolute url
    img.src = null; // no server request
    return url;
}
// Tested successfully in IE6/7, FF2/3, Safari3, Opera9, Chrome (All on Windows XP) 

// EXAMPLE:
var myRelativeURL = 'blah/page.html';
alert( qualifyURL(myRelativeURL) );

Absolute URLs are helpful when shifting a page from one location to another because you don't have to change resource's URLs from within the shifted page.

A good link for parsing or making absolute URLs in JavaScript: https://gist.github.com/1088850

Protocol Level URLS:
<script src="//www.google.com/js/gweb/analytics/autotrack.js"></script>
<img src="//domain/image.jpg" />
Omitting the protocol—which makes the URL relative—prevents mixed content issues and results in minor file size savings.

What is Curvature?




What is the Curvature?
Curvature is a designer for curving. It generates Canvas 2d APIs relevant code in different forms.

Top Features
Curvature allows you:
  • Curves alignment (in any shape, in any portion of the page, to any point!) 
  • Drag whole drawing (all curves at a time!) 
  • Drag a single curve (all points at a time) 
  • Copy whole drawing and dragging-ability! Generates code in 4 forms: 1) relative coordinates 2) shortened relative coordinates 3) absolute coordinates 4) shortened absolute coordinates
Other common features
  • Undo support (for unlimited curves; whether millions of curves!) 
  • Starting and ending points replacement for a Bezier curve (sometimes: useful) 
  • Auto creates new curves (on mouse movement – on demand!) 
  • Fill color (in the last curve – clarifies the curve!)

New version of Curvature allows you hide/show the coding area so you can have a full drawing surface now!

Source code (Github!)
Source code of Curvature available at Github! https://github.com/muaz-khan/Curvature



What is "Shorten the code"?
This feature shortens the lines of auto generated code! Also it reduces size of the page!

Explain "Make relevant startingX/startingY points"
This feature was included in the first release of the Curvature. It generates relevant code from two points: startingX and startingY.

This feature allows you use e.pageX/e.pageY on these two points so you can easily drag/move whole shape (all curves at a time) without any disturbance.

Is it useful: "Replace starting and ending points' positions at new curve"?
Sure, in the complex shapes – I used it often.

"Auto create new curves" – what is this?
To auto create new curves at mouse movement. You don't have to click "New Curve" button or press "N" key to create new curve(s).

"Temporarily fill a color in the last curve" – isn't it a redundant feature?
For redundancy: it can be a redundant feature. However I included it for those who want to clarify the last curve!

"Drag whole curve/drawing" – Explain
  • "Drag whole curve" feature drags last curve as it is without any disturbance in the real shape of the "last" curve. 
  • "Drag whole drawing" drags whole drawing (at x-y coordinates) without any disturbance in the real shape(s).
Both are most useful features in the Curvature!

"Copy current drawing (all curves)" – isn't it limited?
This feature copies whole drawing and allows you drag "copied drawing". It is limited because it allows only one "paste" for copied drawing. Upcoming version of Curvature may support it fully – till that; use it carefully!

Curves alignment – digging into it



Curvature allows you align curves in two styles:
  • "Align Vertically":- Aligns y-coordinates of all (or selected) points. 
  • "Align Horizontally" (default selected):- Aligns x-coordinates of all (or selected) points.

"Align to relevant topmost points" (default selected) – aligns points with topmost (or first drawn) curve's relevant points.

You can set custom points too for alignment.

Test the tool: https://canvature.appspot.com/

Dragging/Moving shapes smoothly using Canvas 2d APIs


Did you ever write code to drag or move shapes using HTML5 Canvas 2d APIs? If you did, then didn't you ever face a situation (an unexpected behaviour) when you drag or move a shape (e.g. circle, rectangle, image, Bezier cubic/quadratic curve, etc.)?

Fore a live example, please test following demo. Drag any shape (from its any corner):


Didn't you face a sudden jerk on the shape?

Test bottom-part of the demo too. It is working smoothly. There is no sudden jerk!

Let us dig into both examples

circleX = e.pageX - canvas.offsetLeft;
circleY = e.pageY - canvas.offsetTop;

context.arc(circleX, circleY, 50, 0, Math.PI * 2, false);

Each workaround regarding the shape's width/height or radius is inefficient or non-smooth:
  • Extraction of the radius (one or two times) to accurately position the circle
  • Subtraction of half width/height of the shape (rectangle/image) to position it accordingly
Second example/demo is the solution!

But for second example, I've not used pageX/pageY directly; instead I'm doing following steps:

  • Tracking first/previous mouse-down or touch position (x-y coordinates)
  • Extracting the dragged distance from those coordinates
  • Adding or subtracting the distance from shape's coordinates according to the dragging direction (positive or negative x-y axis)


/* Global Variable */
var previousPoints = [0, 0];

/* Mouse Down event! */
{
    var x = ( e.pageX - canvas.offsetLeft ), y = ( e.pageY - canvas.offsetTop );
    
    /* Saving last x-y coordinates! - on mousedown */
    previousPoints = [x, y];
}

/* Mouse Move event! */
{    
    var x = e.pageX - canvas.offsetLeft,
        y = e.pageY - canvas.offsetTop,
    
        /* Previous points: x-y */
        prevX = previousPoints[0],
        prevY = previousPoints[1];
    
        /* Drag direction! */
        positiveX = x > prevX, 
        positiveY = y > prevY, 
    
        /* The dragged distance! */
        value;

    /* This value will be used for x-coordinates */
    value = positiveX ? (x - prevX) : (prevX - x);
    if (positiveX) 
        circleX += value;
    else 
        circleX -= value;

    /* This value will be used for y-coordinates */
    value = positiveY ? (y - prevY) : (prevY - y);
    if (positiveY) 
        circleY += value;
    else 
        circleY -= value;

    /* Saving last x-y coordinates! - on mousemove */
    previousPoints = [x, y];
}

/* And to draw the circle! */
context.arc(circleX, circleY, 50, 0, Math.PI * 2, false);

Quick updates in the Curvature

https://canvature.appspot.com/

Summary: “Now you can directly share code with others!”
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
Test what I shared with you!
① http://goo.gl/5MdKo 
② http://goo.gl/tZAuJ 
③ http://goo.gl/XXVjg
④ http://goo.gl/Y8NqT
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
This feature is not only helpful for sharing but also for saving your last drawing or settings via bookmarking.

Click → “Share” button – and share URL! (Hint: use http://goo.gl/ to shorten the URL!!)
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
★ Note ⇒ Sometimes URL goes too long. In that case, open browser specific dev-tool (F12 or whatever shortcut!) and type location.hash in the Console window/section. (And copy!)