DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest JavaScript Topics

article thumbnail
All the mouse events in JavaScript
The HTML 5 specification is full of definitions of new events, but it gathers them in a long list only divided by the category of support: some must be supported by all elements, some by window and derivatives, and so on. Unfortunately this style mixes up many different kinds of events, like the multimedia (canplay) and keyboard-based ones (keyup). In this article, I have collected all events that can be generated with a mouse. In HTML 4 There are a few well-supported events ported by the previous version of the specification. Everyone would expect a browser to correctly fire these events: click: the simplest event. dblclick: fired on a double click on an HTML element. mousedown: fired when the button is pressed. mouseup: fired when the button is released. mouseover: fired when the cursor passes over an HTML element. mouseout: fired when the cursor leaves the displaying area of an HTML element; the inverse of mouseover. mousemove: fired everytime the cursor moves one pixel. It's very easy to hang the browser by targeting this event. In any case, window.addEventListener and element.addEventListener (where element is a reference to a DOM element) are the functions to call to setup event handlers. You could also use the on$eventName HTML attribute or property (e.g. onclick, onmouseover), but addEventListener is more flexible as it allows for many different listeners to work on the same event, without one silently replacing the other. HTML 5: dragging Most of the new mouse events (but not necessarily the most interesting ones) deal with drag and drop support: drag: fired frequently on a dragged element (which must define the *draggable* attribute.) dragstart: fired when the mouse is held down on an element and the movement starts. dragend: fired when the element is released. dragenter: fired when an element enters the displayed area of another one. dragleave: fired when an element exits the displayed area, as the inverse of dragenter. dragover: fired frequently when an element is over another. drop: fired when an element is released over another. drag, dragstart, and dragend are fired on the dragged element, while dragenter, dragleave, dragover and drop are fired on the target one. Here is a self-contained example of their usage: One of the common usages of the Drag and Drop API is the integration with the File API to allow for upload of files by dragging into the browser's window. HTML 5: the wheel The mousewheel event is fired upon the usage of the wheel over an element or the window. Here is an example that zooms in or out of an HTML element by modifying its size: The scroll event instead works at an higher-level of abstraction: it is not really a mouse-specific event, as it can be generated by the mouse but also by pressing scrolling keys. What the event models is a change in the visible section of an element, generated by a movement in the vertical or horizontal scrollbars: Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... Lorem ipsum dolor amet... HTML 5: right click The contextmenu event is fired upon a right click, that opens a contextual menu centered on the mouse pointer. Here is an example of interception: If you want to display an alternate contextual menu, you would also probably want to cancel the event; however, many browsers allow the user to override these manipulations and always show the original menu (think of websites hiding the View Source entry).
March 7, 2012
by Giorgio Sironi
· 79,670 Views
article thumbnail
Streaming Radio Player Tutorial with Live Demo and Source Code
today i have prepared another really great tutorial for you. recently i started development of my own radio software (as a module for dolphin cms) and got some interesting results i would like to share with you. it will be nice looking (css3) radio script that consists of three main elements: the header (with animated search bar and integrated radio player), the left side (with a list of categories and subcategories) and the right side (which will contain a list of recent or filtered stations). here's the final result of our player: here's our live demo and downloadable package: ok, download our source files and lets start coding! step 1. html markup this is the markup of one of the template files. this is a template of our main (index) page: templates/main_page.html stream radio script back to original tutorial on script tutorials alternative classic alternativeindustrialnew wavepunk classical modernoperapianoromanticsymphony electronic breakbeatdanceelectrohousetechnotrance metal classic metalheavy metalmetalcorepower metal pop dance popoldiestop 40world pop __stations__ powered by script tutorials first, pay attention to how the script loads the jquery library from google. this can be pretty useful if you don’t like to keep this file directly on your host. our header element contains a nice search bar with an embedded jasl player ( i used a great ffmp3 live stream player ), which allows us to play audio streams without any problems. next, on the left-hand side (beneath the header) we have a ul-li based list of categories and subcategories. the right-hand side will contain a list of the most recent stations and, when we search or select a category, the right-hand side will be filtered by ajaxy. for now – it contains __stations__ key (template key) and we will replace the actual value with php. on to our next template file, the radio player: templates/radio.html of course, it contains its own template keys (__title__ and __stream__) which we will use after. step 2. css here are our stylesheets files: css/main.css the first one contains the styles of our test page (this file is always available in our package) css/radio.css /* header area */ .header { height:62px; } .header input { background:#aaa url(../images/search.png) no-repeat 5px center; border:1px solid #888; border-radius:10px; float:right; margin:14px 10px 0 0; outline:none; padding-left:20px; width:200px; -webkit-transition: 0.5s; -moz-transition: 0.5s; -o-transition: 0.5s; transition: 0.5s; } .header input:focus { background-color:#eee; width:300px; } .header > span { display:block; float:left; line-height:40px; padding:7px; -webkit-transition: 0.5s; -moz-transition: 0.5s; -o-transition: 0.5s; transition: 0.5s; } /* stations list */ .stlist { float:right; margin-right:1%; width:71%; } .stlist ul { list-style:none outside none; margin:0; padding:0; } .stlist ul li { border-bottom:1px dotted #444; overflow:hidden; padding:10px; } .stlist ul li > a > img { border:1px solid #ccc; float:left; height:85px; margin-right:15px; padding:1px; width:85px; } .stlist ul li > div { float:right; margin-left:15px; margin-top:-5px; } .stlist ul li > p.label,.stlist ul li > p.track { font-size:11px; font-weight:700; } .stlist ul li > p.label { color:#888; } .stlist ul li > p.channel { font-size:14px; font-weight:700; margin-bottom:17px; } /* genres list */ .genres_par { border-right:1px solid #ccc; float:left; width:26%; } ul.genres,ul.genres ul { list-style-type:none; margin:0; padding:0; } ul.genres ul { display:none; overflow:hidden; padding:0 15px; } ul.genres ul li { margin:3px; } ul.genres a { color:#333; display:block; font-size:18px; padding:4px 0; text-align:center; text-decoration:none; } ul.genres ul a { font-size:12px; text-align:left; } ul.genres li { border-bottom:1px solid #ccc; margin:0; } ul.genres li ul li a { background:none repeat scroll 0 0 #5bb951; border-radius:2px; color:#fff; font-size:12px; padding:6px; } ul.genres li ul li a:hover { background-color:#53854e; } step 3. js js/script.js $(document).ready(function(){ $('#search').blur(function() { if ('' == $('#search').val()) $('#search').val('search'); }); $('#search').focus(function() { if ('search' == $('#search').val()) $('#search').val(''); }); $('ul.genres li a').click( // category slider function() { var checkelement = $(this).next(); if((checkelement.is('ul')) && (!checkelement.is(':visible'))) { $('.genres li ul').slideup(150); $(this).next().slidetoggle(150); } } ); $('ul.genres ul li a').click( // get stations by category function() { $.ajax({ type: 'get', url: 'index.php', data: 'action=get_genre_stations&id=' + $(this).parent().attr('id') + '&name=' + $(this).parent().attr('val'), success: function(data){ $('.stlist').fadeout(400, function () { $('.stlist').html(data); $('.stlist').fadein(400); }); } }); } ); }); function play(id) { // play function $('#rplayer').load('index.php?action=play&id=' + id, function() {}); return false; } function get_stations_by_keyword() { // get stations by keyword var keyword = $('#search').val().replace(/ /g,"+"); $.ajax({ type: 'get', url: 'index.php', data: 'action=get_keyword_stations&key=' + keyword, success: function(data){ $('.stlist').fadeout(400, function () { $('.stlist').html(data); $('.stlist').fadein(400); }); } }); } as you see – there's nothing difficult there. just several event handlers, and two new functions (to play radio station and to search for stations by keyword). step 4. php index.php =') == 1) error_reporting(e_all & ~e_notice & ~e_deprecated); else error_reporting(e_all & ~e_notice); $astations = array( 0 => array( 'category' => 31, 'name' => 'eurodance', 'desc' => 'the newest and best of eurodance hits', 'url' => 'http://www.di.fm/eurodance', 'br' => 96, 'stream' => 'http://scfire-mtc-aa06.stream.aol.com:80/stream/1024' ), 1 => array ( 'category' => 34, 'name' => 'house', 'desc' => 'silky sexy deep house music direct from new york city!', 'url' => 'http://www.di.fm/house', 'br' => 96, 'stream' => 'http://scfire-ntc-aa04.stream.aol.com:80/stream/1007' ), 2 => array ( 'category' => 13, 'name' => 'trance', 'desc' => 'the hottest, freshest trance music from around the globe!', 'url' => 'http://www.di.fm/trance', 'br' => 96, 'stream' => 'http://scfire-ntc-aa04.stream.aol.com:80/stream/1003' ), 3 => array ( 'category' => 51, 'name' => 'electro house', 'desc' => 'an eclectic mix of electro and dirty house', 'url' => 'http://www.di.fm/electro', 'br' => 96, 'stream' => 'http://scfire-ntc-aa04.stream.aol.com:80/stream/1025' ) ); function searchbycat($icat, $astations) { $ares = array(); foreach ($astations as $i => $ainfo) { if ($ainfo['category'] == $icat) { $ares[$i] = $ainfo; } } return $ares; } function searchbykeyword($skey, $astations) { $ares = array(); foreach ($astations as $i => $ainfo) { if (false !== strpos($ainfo['name'], $skey) || false !== strpos($ainfo['desc'], $skey)) { $ares[$i] = $ainfo; } } return $ares; } function parsestationlist($adata) { $sstations = ''; if (is_array($adata) && count($adata) > 0) { foreach ($adata as $i => $a) { $sstationid = $i; $sstationbr = (int)$a['br']; $sstationname = $a['name']; $sstationdesc = $a['desc']; $sstationurl = $a['url']; $sthumb = 'media/'.($sstationid+1).'.png'; $sstations .= << bitrate: {$sstationbr} {$sstationname} {$sstationdesc} {$sstationurl} eof; } } $sstations = ($sstations == '') ? 'nothing found' : $sstations; return '' . $sstations . ''; } switch ($_get['action']) { case 'play': $i = (int)$_get['id']; $ainfo = $astations[$i]; $avars = array ( '__stream__' => $ainfo['stream'], '__title__' => $ainfo['name'] ); echo strtr(file_get_contents('templates/radio.html'), $avars); exit; break; case 'get_genre_stations': $i = (int)$_get['id']; $asearch = searchbycat($i, $astations); $sstations = parsestationlist($asearch); header('content-type: text/html; charset=utf-8'); echo $sstations; exit; break; case 'get_keyword_stations': $skey = $_get['key']; $asearch = searchbykeyword($skey, $astations); $sstations = parsestationlist($asearch); header('content-type: text/html; charset=utf-8'); echo $sstations; exit; break; } $slaststations = parsestationlist($astations); echo strtr(file_get_contents('templates/main_page.html'), array('__stations__' => $slaststations)); at the beginning, i have prepared a list of our radio stations (4 stations total). then, two search functions: ‘searchbycat’ and ‘searchbykeyword’. next, the special function ‘parsestationlist’ which will transform array with filtered stations into its html representation. finally, a little switch case to manage with our inner ajax commands. conclusion you are always welcome to enhance our script and share your ideas. i will be glad to see your thanks and comments. good luck!
February 29, 2012
by Andrei Prikaznov
· 51,507 Views · 1 Like
article thumbnail
Running JavaScript inside PHP code
v8js is a new PHP extension able to run JavaScript code inside V8, Google's JavaScript interpreter that powers for example Chrome and NodeJS. This extension is highly alpha - and its API would probably change in the months ahead. Since documentation is lacking, I invite you to repeat the discovering process I follow in this post in case you find some differences in a new version of v8js. Installation V8 must be present on the machine in order to install the extension. On a Debian/Ubuntu system, run the following: sudo apt-get install libv8-dev libv8-dbg libv8-dev will also install libv8 in its latest version. Afterwards, download and compile the extension with: sudo pecl install v8js There are no more requirements for compilation apart from the usual dependencies for PECL packages, like build-essential. After that, add: extension=v8js.so to php.ini or to a section in conf.d. $ php -m | grep v8 v8js will confirm you the extension is loaded. Some introspection PHP's reflection let us take a look at the classes and methods provided by this extension, even without documentation available. It probably hasn't been written yet, due to the unstable API. $ php -r 'var_dump(get_declared_classes());' | grep V8 string(8) "V8Object" string(10) "V8Function" string(4) "V8Js" string(13) "V8JsException" $ php -r '$class = new ReflectionClass("V8Js"); var_dump($class->getMethods());' array(5) { [0]=> &object(ReflectionMethod)#2 (2) { ["name"]=> string(11) "__construct" ["class"]=> string(4) "V8Js" } [1]=> &object(ReflectionMethod)#3 (2) { ["name"]=> string(13) "executeString" ["class"]=> string(4) "V8Js" } [2]=> &object(ReflectionMethod)#4 (2) { ["name"]=> string(19) "getPendingException" ["class"]=> string(4) "V8Js" } [3]=> &object(ReflectionMethod)#5 (2) { ["name"]=> string(17) "registerExtension" ["class"]=> string(4) "V8Js" } [4]=> &object(ReflectionMethod)#6 (2) { ["name"]=> string(13) "getExtensions" ["class"]=> string(4) "V8Js" } } $ php -r '$v8 = new V8Js(); var_dump($v8->executeString("1+2+3"));' int(6) Interesting! We have just executed our first JavaScript expression inside a PHP process. Apparently the last statement's value is returned by the executeString() method, with a rough conversion preserving the type: $ php -r '$v8 = new V8Js(); var_dump($v8->executeString("var obj = {}; obj.field = 1; obj.field++; obj.field;"));' int(2) Syntax or runtime errors are signaled with a V8JsException: $ php -r '$v8 = new V8Js(); var_dump($v8->executeString("var obj = {"));' PHP Fatal error: Uncaught exception 'V8JsException' with message 'V8Js::executeString():1: SyntaxError: Unexpected end of input' in Command line code:1 Stack trace: #0 Command line code(1): V8Js->executeString('var obj = {') #1 {main} thrown in Command line code on line 1 Let's add more difficulty The FizzBuzz kata OO solution is an example of JavaScript code creating an object and executing anonymous functions: it's a good test bench for our integration.Since evaluating a variable as the last line returns it, that is our channel of communication, supporting integers, strings, floats, booleans, arrays (not objects at this time). Meanwhile, input for JavaScript code can be embedded into the executed string. This code will output string(8) "FizzBuzz": executeString($javaScriptCode)); By changing it a bit, we can build a JSON string by backslashing the double quotes ("), and returns it in lieu of an object to communicate to the PHP process a complex result: ... var myFizzBuzz = new FizzBuzz({3 : "Fizz", 5 : "Buzz"}); "{\"15\" : \"" + myFizzBuzz.accept(15) + "\", \"5\" : \"" + myFizzBuzz.accept(5) + "\"}"; '; $v8 = new V8Js(); $result = $v8->executeString($javaScriptCode); var_dump($result); var_dump(json_decode($result)); The output is: string(33) "{"15" : "FizzBuzz", "5" : "Buzz"}" object(stdClass)#2 (2) { ["15"]=> string(8) "FizzBuzz" ["5"]=> string(4) "Buzz" } Wiring Executing an external script would be nice: it would provide better stack traces, with traceable line numbers at the JavaScript level. It would also mean we won't need backslashing for single quotes, simplifying the syntax. We cannot load scripts on the JavaScript side out of the box, due to V8 missing this functionality (Node JS adds this feature) but we can load the code on the PHP Side: // test.js $ php loadingfiles.php string(24) "test.js file was loaded." // loadingfiles.php executeString($javascriptCode); var_dump($result); Execution results in: $ php loadingfiles.php string(24) "test.js file was loaded." However, we still miss the capability of including JavaScript libraries. Conclusion There are many possible use cases for v8js, like sandboxed scripting or the integration of some code which was written for the client side. That would not be the most clean solution, but it's a Turing complete approach, so why not? After all, it's already possible to run PHP on Java or Python and Ruby on .NET. JavaScript is becoming ubiquitous, so why not providing support for it, even in a caged box?
February 29, 2012
by Giorgio Sironi
· 52,616 Views
article thumbnail
WCF and Node.js, better together
(get wcf.js on github!) Take a look at the following code: var binding = new WSHttpBinding( { MessageEncoding: "Mtom" , SecurityMode:"TransportWithMessageCredential" }) , proxy = new Proxy(binding) proxy.ClientCredentials.Username.Username = "yaron"; proxy.ClientCredentials.Username.Password = "1234"; proxy.send(message, function(response) { console.log(response) }); Do you see anything...um, special? Well c# already has the "var" keyword since version 3.0 so maybe it is some kind of a c#-ish dialect? Or maybe it is a CTP for javascript as a CLR language? Or something related to the azure sdk for node.js? Not at all. This is a snippet from wcf.js - a pure javascript node.js module that makes wcf and node.js work together! As node assumes its central place in modern web development, many developers build node apps that must consume downstream wcf services. Now if these services use WCF Web API ASP.NET Web API it is very easy. It is also a breeze if you are in a position to add a basic http binding to the Wcf service, and just a little bit of more work if you plan to employ a wcf router to do the protocol bridging. Wcf.js is a library that aims to provide a pure-javascript development experiece for such scenarios. Note that building new node.js ws-* based services is a non-goal for this project. Putting aside all the religious wars, Soap is not the "node way", so you should stick to Rest where you'll get good language support (json) and built-in libraries. "Hello, Wcf... from node" You are closer than you think to consume your first Wcf service node.js: 1. Create a new wcf web site in VS and call it "Wcf2Node". If you use .Net 4 than BasicHttpBinding is the default, otherwise in web.config replace WsHttp with BasicHttp. No need to deploy, just run the service in VS using F5. 2. Create anywhere a folder for the node side and from the command line enter its root and execute: $> npm install wcf.js 3. In the same folder create test.js: var BasicHttpBinding = require('wcf.js').BasicHttpBinding , Proxy = require('wcf.js').Proxy , binding = new BasicHttpBinding() , proxy = new Proxy(binding, " http://localhost:12/Wcf2Node/Service.svc") , message = '' + '' + '' + '' + '123' + '' + '' + '' proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) { console.log(response) }); 4. In test.js, change the port 12 (don't ask...) to the port your service runs on. 5. Now we can execute node: $> node test.js 6. You should now see the output soap on the console. Of course this sample is not very interesting and you may be better off sending the raw soap using request. Let's see something more interesting. If your service uses ssl + username token (transport with message credential), the config may look like this: The following modifications to the previous example will allow to consume it from node: ... binding = new WSHttpBinding( { SecurityMode: "TransportWithMessageCredential" , MessageClientCredentialType: "UserName" }) ... proxy.ClientCredentials.Username.Username = "yaron"; proxy.ClientCredentials.Username.Password = "1234"; proxy.send(...) And here is the wire soap: 2012-02-26T11:03:40Z 2012-02-26T11:08:40Z yaron 1234 123 If you use Mtom check out this code: (The formatting here is a bit strage due to my blog layout - it looks much better in github!) var CustomBinding = require('wcf.js').CustomBinding , MtomMessageEncodingBindingElement = require('wcf.js').MtomMessageEncodingBindingElement , HttpTransportBindingElement = require('wcf.js').HttpTransportBindingElement , Proxy = require('wcf.js').Proxy , fs = require('fs') , binding = new CustomBinding( [ new MtomMessageEncodingBindingElement({MessageVersion: "Soap12WSAddressing10"}), , new HttpTransportBindingElement() ]) , proxy = new Proxy(binding, "http://localhost:7171/Service/mtom") , message = '' + '' + '' + '' + '' + '' + '' + '' + '' + '' proxy.addAttachment("//*[local-name(.)='File1']", "me.jpg"); proxy.send(message, "http://tempuri.org/IService/EchoFiles", function(response, ctx) { var file = proxy.getAttachment("//*[local-name(.)='File1']") fs.writeFileSync("result.jpg", file) }); Mtom is a little bit trickier since wcf.js needs to know which nodes are binary. Using simple xpath can help you achieve that. Getting your hands dirty with Soap Wcf.js uses soap in its raw format. Code generation of proxies does not resonate well with a dynamic language like javascript. I also assume you are consuming an existing service which already has working clients so you should be able to get a working soap sample. And if you do like some level of abstraction between you and your soap I recommend node-soap, though it still does not integrate with wcf.js. If you will use raw soap requests and responses you would need a good xml library. And while node has plenty of dom / xpath libraries, they are not windows friendly. My next post will be on a good match here. Supported standards Wcf implements many of the ws-* standards and even more via proprietary extensions. The first version of wcf.js supports the following: MTOM WS-Security (Username token only) WS-Addressing (all versions) HTTP(S) The supported binding are: BasicHttpBinding WSHttpBinding CustomBinding What do you want to see next? Let me know. Get the code Wcf.js is hosted in GitHub, and everyone is welcome to contribute features and fixes if needed. Wcf.js is powered by ws.js, the actual standards implementation, which I will introduce in an upcoming post.
February 25, 2012
by Yaron Naveh
· 19,821 Views
article thumbnail
Introduction to Kendo UI
kendo ui is html 5 and jquery based framework and it helps you to create modern web applications. kendo ui helps you in data binding in animations with ui widgets like grid and chart with drag and drop api in touch support. download kendo ui from here once you download you get these folders: navigate to the 'example' folder for examples of various widgets. if you want to start developing web applications using kendoui then you need to add the required file in your project. you need to add the below files in the script folder: and you need to add the below files in the style folder: even though i have added script files and css files in the script folder and style folders respectively, you are free to keep them anywhere you want. after adding these files you need to link them in the header of the html page. you can add the reference as below: in a later post i will go into the details of kendo ui and play around with all other aspects. however, working with any widgets is very intuitive. for example, if you want to work with kendo autocomplete , you can do that as below: and using jquery you can assign the value as below: putting all html and script code together: test.htm kendo ui demo when you run test.htm in your browser, you should get this output: in later posts i will get into detail about all widgets. i hope this post is useful. thanks for reading. source: http://debugmode.net/2012/02/18/introduction-to-telerik-kedno-ui/
February 20, 2012
by Dhananjay Kumar
· 19,873 Views · 1 Like
article thumbnail
Track a Moving Ball in Real Time using HTML5 and JavaScript
This is an experiment for a real-time tracking of a football match using only web technologies. In this case I’ve chosen to track a football match from Futbol Club Barcelona (fcb). All the work is made by the browser and it’s interactive (there are four checkboxes to activate/deactivate each tracker). It is based on tracking the location of colored objects in the frames using the HSV colour space. As a practical use for the tracker, I’ve added a smart volume feature that activates the sound only when there are goal chances (every time the ball is near the area). So you can browse other pages and change to the video one only when chances are happening. It works based on the quantity of green color in the sides of the video. The path tracker shows ‘possible’ passes between fcb players If you want to watch it in action here is the demo So far it only works in chrome and firefox and because of the low resolution of the video (and my limited skills), the tracking is not perfect, but it could be improved for tracking videos from external sources like Youtube, Veetle, etc. Here is the code: function rgbToHsv(r, g, b){ r = r/255, g = g/255, b = b/255; var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, v = max; var d = max - min; s = max == 0 ? 0 : d / max; if(max == min){ h = 0; // achromatic }else{ switch(max){ case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, v]; } //Main object var processor = { isFirefox35: function() { // Let a chance to the navigator to deal with it: return true; var ua = navigator.userAgent; // Gecko ? if (ua.indexOf("Gecko") == -1) return false; // Geck >= 1.9.1 ? return !(ua.indexOf("rv:1.9.1") == -1 && ua.indexOf("rv:1.9.2") == -1); }, // Init doLoad: function() { if (!this.isFirefox35()) { document.getElementById("nofirefoxbeta").style.display = "block"; } // Some init this.displayBackground = true; this.video = document.getElementById("video"); this.mirrorVideo = document.getElementById("mirrorVideo"); this.mirrorVideoCtx = this.mirrorVideo.getContext("2d"); var self = this; // If the videos end, play again this.video.addEventListener("ended", function(){ try { clearTimeout(self.timeout); } catch(e){} self.video.play(); // Work around: https://bugzilla.mozilla.org/show_bug.cgi?id=488287 self.videoIsPlaying(); }, true); // Set the events listeners for the main video (update button) this.video.addEventListener("pause", function() { self.updateButtons(false); }, false); this.pageLoaded = true; this.startPlayer(); }, videoIsPlaying: function() { this.updateButtons(true); this.timerCallback(); }, videoIsReady: function() { this.videoLoaded = true; this.startPlayer(); }, startPlayer: function() { if (!this.videoLoaded || !this.pageLoaded) return; document.getElementById("wait").style.display = "none"; document.getElementById("player").style.display = "block"; this.width = this.video.videoWidth; this.height = this.video.videoHeight; this.mirrorVideo.width = this.width; this.mirrorVideo.height = this.height; }, playVideo:function(){ this.video.play(); this.videoIsPlaying(); }, stopVideo: function(){ this.video.pause(); clearTimeout(this.timeout); }, volumeDown:function(){ if(this.video.volume>0) this.video.volume=Math.round((this.video.volume - 0.1)*10)/10; }, volumeUp:function(){ if(this.video.volume<1) this.video.volume=Math.round((this.video.volume + 0.1)*10)/10; }, // Main loop timerCallback: function() { if (this.video.paused || this.video.ended) { return; } this.computeFrame(); var self = this; this.timeout = setTimeout(function () { self.timerCallback(); }, 50); }, // Update the SVG button updateButtons: function(play) { document.getElementById("playButton").setAttribute("play", play); document.getElementById("stopButton").setAttribute("play", play); }, // Handling some patterns (text, drawing) has_green_around: function(frameData, pos) { pos_left = pos+ 24; pos_right = pos - 24; r_left = frameData[pos_left+0]; g_left = frameData[pos_left+1]; b_left = frameData[pos_left+2]; r_right = frameData[pos_right+0]; g_right = frameData[pos_right+1]; b_right = frameData[pos_right+2]; return ((r_left < 125 && g_left > 125 && b_left < 80) && (r_right < 125 && g_right > 125 && b_right < 80)); }, is_team_color: function(frameData, pos){ for (i=pos-4; i<=pos+4; i+=4){ r = frameData[i+0]; g = frameData[i+1]; b = frameData[i+2]; hsv = rgbToHsv(r,g,b); //if(hsv[0] < 0.60|| hsv[1] < 0.35) if((hsv[0] < 0.40 || hsv[1] < 0.25 || hsv[2] < 0) || (hsv[0] > 0.70 || hsv[1] > 1 || hsv[2] > 1)) return false; } return true; }, is_ball_color: function(frameData, pos){ for (i=pos-4; i<=pos+4; i+=4){ r = frameData[i+0]; g = frameData[i+1]; b = frameData[i+2]; hsv = rgbToHsv(r,g,b); if((hsv[0] < 0.23 || hsv[1] < 0.40 || hsv[2] < 0.90) || (hsv[0] > 0.27 || hsv[1] > 0.50 || hsv[2] > 1)) return false; } return true; }, dist: function(x1, y1, x2, y2) { return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }, computeFrame: function() { try { this.mirrorVideoCtx.clearRect(0, 0, this.width, this.height); this.mirrorVideoCtx.drawImage(this.video, 0, 0, this.width, this.height); } catch(e) { return; } var frame = this.mirrorVideoCtx.getImageData(0, 0, 640, 360); this.mirrorVideoCtx.fillStyle = 'rgba(200,200,200,0.5)'; this.mirrorVideoCtx.strokeStyle = 'rgba(200,200,200,0.5)'; this.mirrorVideoCtx.lineWidth = 1; var x, y; var weight = 0; var team_shape = null; var ball_shape = null; var ball_found = false; var ball_tracker = document.getElementById("balltracker").checked; var team_tracker = document.getElementById("teamtracker").checked; var path_tracker = document.getElementById("pathtracker").checked; var smart_volume = document.getElementById("smartvolume").checked; var shapes = []; var x, y; var green_bar_left = 0; var green_bar_rigth =0; var green_bar_down = 0; var frame_length = frame.data.length/4; // We dont' need to compute each pixels var step = 4; for (var i = 0; i < frame_length; i += step) { pos = i*4; x = i % this.width; y = Math.round(i / this.width); if (x == 4) green_bar_left += g; else if (x == this.width-4) { green_bar_rigth += g; if (y == 4) green_bar_down += g; } ball_found = ball_tracker && this.is_ball_color(frame.data, pos); team_found = team_tracker && this.is_team_color(frame.data, pos); if (this.has_green_around(frame.data, pos) && (ball_found || team_found)){ if (ball_found) { ball_shape = {}; ball_shape.x = x; ball_shape.y = y; } if(team_found) { if (!team_shape) { // no shape yet, create the first one team_shape = {}; team_shape.x = x; team_shape.y = y; team_shape.weight = 1; shapes.push(team_shape); } else { var d = this.dist(x, y, team_shape.x, team_shape.y); if (d>25){ team_shape = {}; team_shape.x = x; team_shape.y = y; team_shape.weight = 1; shapes.push(team_shape); } } } } } if (shapes.length>0) { if (path_tracker){ this.mirrorVideoCtx.beginPath(); this.mirrorVideoCtx.moveTo(shapes[0].x, shapes[0].y); } for( var s=0; s0 && Math.abs(green_left_average-green_right_average)>15){ //this.volumeUp(); this.video.volume=1; document.getElementById("soundIcon").setAttribute("mute", false); }else{ this.volumeDown(); //this.video.volume=0; document.getElementById("soundIcon").setAttribute("mute", true); } } return; } } Source: http://lusob.com/2012/02/tracking-a-football-match-with-html5-and-javascript/
February 19, 2012
by Luis Sobrecueva
· 17,771 Views · 1 Like
article thumbnail
Access Server Side Variable In Javascript
Add following javascript function to aspx page function check() { alert("this is check value " + ''); } Add following variable declaration on server side i.e aspx.cs public string checkvalue ="indrnilhafa";
January 31, 2012
by Snippets Manager
· 7,687 Views
article thumbnail
JavaScript to Convert Date to MM/DD/YYYY Format
In this post, you'll find a quick, 7-line code block of JavaScript that you can use to covert dates to the MM/DD/YYYY format.
January 27, 2012
by Snippets Manager
· 479,680 Views · 8 Likes
article thumbnail
Algorithm of the Week: Data Compression with Bitmaps
In my previous post we saw how to compress data consisting of very long runs of repeating elements. This type of compression is known as “run-length encoding” and can be very handy when transferring data with no loss. The problem is that the data must follow a specific format. Thus the string “aaaaaaaabbbbbbbb” can be compressed as “a8b8”. Now a string with length 16 can be compressed as a string with length 4, which is 25% of its initial length without loosing any information. There will be a problem in case the characters (elements) were dispersed in a different way. What would happen if the characters are the same, but they don’t form long runs? What if the string was “abababababababab”? The same length, the same characters, but we cannot use run-length encoding! Indeed using this algorithm we’ll get at best the same string. In this case, however, we can see another fact. The string consists of too many repeating elements, although not arranged one after another. We can compress this string with a bitmap. This means that we can save the positions of the occurrences of a given element with a sequence of bits, which can be easily converted into a decimal value. In the example above the string “abababababababab” can be compressed as “1010101010101010”, which is 43690 in decimals, and even better AAAA in hexadecimal. Thus the long string can be compressed. When decompressing (decoding) the message we can convert again from decimal/hexadecimal into binary and match the occurrences of the characters. Well, the example above is too simple, but let’s say only one of the characters is repeating and the rest of the string consists of different characters like this: “abacadaeafagahai”. Then we can use bitmap only for the character “a” – “1010101010101010” and compress it as “AAAA bcdefghi”. As you can see all the example strings are exactly 16 characters and that is a limitation. To use bitmaps with variable length of the data is a bit tricky and it is not always easy (if possible) to decompress it. Basically bitmap compression saves the positions of an element that is repeated very often in the message! In the other hand bitmap compression is not only applicable on strings. We can compress also arrays, objects or any kind of data. The example from my previous post is very suitable. Then we had to transfer a large array from a server to the client (browser) using JSON. The data then was very suitable for “run-length encoding”. Now let’s assume we have the same data – a set of different years, which this time are dispersed in a different way. $data = array( 0 => 1991, 1 => 1992, 2 => 1993, 3 => 1994, 4 => 1991, 5 => 1992, 6 => 1993, 7 => 1992, 8 => 1991, 9 => 1991, 10 => 1991, 11 => 1992, 12 => 1992, 13 => 1991, 14 => 1991, 15 => 1992, ... ); The JSON will encoded message will be the following (a simple but yet very large javascript array). [1991,1992,1993,1994,1991,1992,1993,1992,1991,1991,1991,1992,1992,1991,1991,1992, ...] However if we use bitmap compression we’ll get a “shorter” array. $data = array( 0 => array(1991, '1000100011100110'), 1 => array(1992, '0100010100011001'), 2 => array(1993, '0010001000000000'), 3 => array(1994, '0001000000000000'), ); Now the JSON is: [[1991,"1000100011100110"],[1992,"0100010100011001"],[1993,"0010001000000000"],[1994,"0001000000000000"]] It is obvious that the compression ratio is getting better and better as the uncompressed data grows. In fact, most of us know bitmap compression from images, because this algorithm is largely used for image compression. We can imagine how successful it can be when compressing black and white images (as black and white can be represented as 0 and 1s). Actually it is used for more than two colors (256 for instance) and again the level of compression is very high. Implementation The following implementation on PHP aims only to illustrate the bitmap compressing algorithm. As we know this algorithm can be applicable for any kind of data structures. // too many repeating "a" characters $msg = 'aazahalavaatalawacamaahakafaaaqaaaiauaacaaxaauaxaaaaaapaayatagaaoafaawayazavaaaazaaabararaaaaakakaaqaarazacajaazavanazaaaeanaaoajauaaaaaxalaraaapabataaavaaab'; function bitmap($message) { $i = 0; $bits = $rest = ''; while ($v = $message[$i]) { if ($v == 'a') { $bits .= '1'; } else { $bits .= '0'; $rest .= $v; } $i++; } return number_format(bindec($bits), 0, '.', '') . $rest;; } echo bitmap($msg); // uncompressed: acaaaaadaaaabalaaeaaaaganaaxakaavawamaasavajawaaaayaauaaadalanagaeaeamaarafalaazaaaiasaanaahaaazaraxaalaahaaawaaajasamahaajaakarapanaakaoakaanawalaacamauaamaal // compressed: 152299251941730035874325065523548237677352452096zhlvtlwcmhkfqiucxuxpytgofwyzvzbrrkkqrzcjzvnzenojuxlrpbtvb Application This algorithm is very useful when there is an element in our data that repeats very often, so you need to investigate the nature of the data you want to compress. Actually because of this fact this algorithm is used for image compression as PNG8 or GIF. Source: http://www.stoimen.com/blog/2012/01/16/computer-algorithms-data-compression-with-bitmaps/
January 17, 2012
by Stoimen Popov
· 20,375 Views
article thumbnail
From Java to Node.js
I’ve been developing for quite a while and in quite a few languages. Somehow though, I’ve always seemed to fall back to Java when doing my own stuff – maybe partly from habit, partly because it has in my opinion the best open source selection out there, and party because I liked its mix of features and performance. Originally authored by Matan Amir Specifically though, in the web arena things have been moving fast and furious with new languages, approaches, and methods like RoR, Play!, and Lift (and many others!). While I “get it” regarding the benefits of these frameworks, I never felt the need to give them more than an initial deep dive to see how they work. I nod a few times at their similarities and move on back to plain REST-ful services in Java with Spring, maybe an ORM (i try to avoid them these days), and a JS-rich front-end. Recently, two factors made me deep dive into Node.js. First is my growing appreciation with the progress of the JavaScript front-end. What used to be little JavaScript snippets to validate a form “onSubmit” have evolved to a complete ecosystem of technologies, frameworks, and stacks. My personal favorite these days is Backbone.js and try to use it whenever I can. Second was the first hand feedback I got from a friend at Voxer about their success in using and deploying Node.js at real scale (they have a pretty big Node.js deployment). So I jumped in. In the short time I’ve been using it for some (real) projects, I can say that it’s my new favorite language of choice. First of all, the event-driven (and non-blocking) model is a perfect fit for server side development. While this has existed in the other languages and forms (Java Servlet 3.0, Event Machine, Twisted to name a few), I connected with the easy of use and natural maturity of it in JavaScript. We’re all used to using callbacks anyway from your typical run-of-the-mill AJAX work right? Second is the community and how large its gotten in the short time Node has been around. There are lots of useful open source libraries to use to solve your problems and the quality level is high. Third is that it was just so easy to pick up. I have to admit that my core JavaScript was decent before I started using Node, but in terms of the Node core library and feature set itself, it’s pretty lean and mean and provides a good starting point to build what you need in case you can’t find someone who already did (which you most likely can). So having said all that, I wanted to share what resources helped me get up to speed in Node.js coming from a Java background. Getting to know JavaScript There are lots of good resources out there on Node.js and i’ve listed them below. For me, the most critical piece was getting my JavaScript knowledge to the next level. Because you’ll be spending all your time writing your server code in JavaScript, it pays huge dividends to understand how to take full advantage of it. As a Java developer you’re probably trained to think in OO designs. With me, this was the part that I focused the most on. Fortunately (or unforunately), JavaScript is not a classic OO language. It can be if you shoehorn it, but i think that defeats the purpose. Here is my short list of JavaScript resources: JavaScript: The Good Parts - Definitely a requirement. Chapters 4 and 5 (functions, objects, and inheritance) are probably the most important part to understand well for those with an OO background. Learning Javascript with Object Graphs (part 2, and part 3) – howtonode.org has lots of good Node material, but this 3 part post is a good resource to top off your knowledge from the book. Simple “Class” Instantiation – Another good post I read recently. Worth digesting. Learning Node.js With a good JavaScript background, starting to use Node.js is pretty straightforward. The main part to understand is the asynchronous nature of the I/O and the need to produce and consume events to get stuff done. Here is a list of resources I used to get up to speed: DailyJS’s Node Tutorial - A multipart tutorial for Node on DailyJS’s blog. It’s a great resource and worth going through all the posts. Mixu’s Node Book - Not complete, but still worth it. I look forward to reading the future chapters. Node Beginner Book – A good starter read. How To Node – A blog dedicated to Node.js. Bookmark it. I felt that going through these was more than enough to give me the push I needed get started. Hopefully it does for you too (thanks to the authors for taking the time to share their knowledge!). Frameworks? Java is all about open source frameworks. That’s part of why it’s so popular. While Node.js is much newer, lots of people have already done quite a bit of heavy-lifting and have shared their code with the world. Below is what I think is a good mapping of popular Java frameworks to their Node.js equivalents (from what I know so far). Web MVC In Java land, most people are familiar with Web MVC frameworks like Spring MVC, Struts, Wicket, and JSF. More recently though, the trend towards client-side JS MVC frameworks like Ember.js (SproutCore) and Backbone.js reduces the required feature-set of some of these frameworks. Nonetheless, a good comparable Node.js web framework is Express. In a sense, it’s even more than a web framework because it also provides most of the “web server” functionality most Java developers are used to through Tomcat, Jetty, etc (more specifically, Express builds on top of Connect) It’s well thought out and provides the feature set needed to get things done. Application Lifecycle Framework (DI Framework) Spring is a popular framework in Java to provide a great deal of glue and abstraction functionality. It allows easy dependency injection, testing, object lifecycle management, transaction management, etc. It’s usually one of the first things I slap into a new project in Java. In Node.js… I haven’t really missed it. JavaScript allows much more flexible ways of decoupling dependencies and I personally haven’t felt the need to find a replacement for Spring. Maybe that’s a good thing? Object-Relational Mapping (ORMs) I have mixed feelings regarding ORMs in general, but it does make your life easier sometimes. There is no shortage of ORM librares for Node.js. Take your pick. Package Management Tools Maven is probably most popular build management tool for Java. While it is very flexible and powerful with a wide variety of plug-ins, it can get very cumbersome. Npm is the mainstream package manager for Node.js. It’s light, fast, and useful. Testing Framework Java has lots of these for sure, jUnit and company as standard. There are also mock libraries, stub libraries, db test libraries, etc. Node.js has quite a few as well. Pick your poison. I see that nodeunit is popular and is similar to jUnit. I’m personally testing Mocha. Testing tools are a more personal and subjective choice, but the good thing is that there definitely are good choices out there. Logging Java developers have quite a list of choices when choosing a logger library. Commons logging, log4j, logback, and slf4j (wrapper) are some of the more popular ones. Node.js also has a few. I’m currently using winston and have no complaints so far. It has the logging levels, multiple transports (appenders to log4j people), and does it all asynchronously as well. Hopefully this will help someone save some time when peeking into the world of Node. Good luck! Source: http://n0tw0rthy.wordpress.com/2012/01/08/from-java-to-node-js/
January 10, 2012
by Chris Smith
· 28,830 Views · 2 Likes
article thumbnail
Async file upload with jquery and ASP.NET
Recently before some I was in search of good asynchronous file upload control which can upload file without post back and I have don’t have to write much custom logic about this. So after searching it on internet I have found lots of options but some of the options were not working with ASP.NET and some of work options are not possible regarding context to my application just like AsyncFileUpload from Ajax toolkit.As in my application we were having old version of Ajax toolkit and if we change it than other controls stopped working. So after doing further search on internet I have found a great Juqery plugin which can easily be integrated with my application and I don’t have to write much coding to do same. So I have download that plug from the following link. This plug in created by yvind Saltvik http://www.phpletter.com/Our-Projects/AjaxFileUpload/ After downloading the plugin and going through it documentation I have found that I need to write a page or generic handler which can directly upload the file on the server. So I have decided to write a generic handler for that as generic handler is best suited with this kind of situation and we don’t have to bother about response generated by it. So let’s create example and In this example I will show how we can create async file upload without writing so much code with the help of this plugin. So I have create project called JuqeryFileUpload and our need for this example to create a generic handler. So let’s create a generic handler. You can create a new generic handler via right project-> Add –>New item->Generic handler just like following. I have created generic handler called AjaxFileuploader and following is simple code for that. using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; namespace JuqeryFileUPload { /// /// Summary description for AjaxFileUploader /// public class AjaxFileUploader : IHttpHandler { public void ProcessRequest(HttpContext context) { if (context.Request.Files.Count > 0) { string path = context.Server.MapPath("~/Temp"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); var file = context.Request.Files[0]; string fileName; if (HttpContext.Current.Request.Browser.Browser.ToUpper() == "IE") { string[] files = file.FileName.Split(new char[] { '\\' }); fileName = files[files.Length - 1]; } else { fileName = file.FileName; } string strFileName=fileName ; fileName = Path.Combine(path, fileName); file.SaveAs(fileName); string msg = "{"; msg += string.Format("error:'{0}',\n", string.Empty); msg += string.Format("msg:'{0}'\n", strFileName); msg += "}"; context.Response.Write(msg); } } public bool IsReusable { get { return true; } } } } As you can see in above code.I have written a simple code to upload a file from received from file upload plugin into the temp directory on the server and if this directory is not there on the server then it will also get created by the this generic handler.At the end of the of execution I am returning the simple response which is required by plugin itself. Here in message part I am passing the name of file uploaded and in error message you can pass error if anything occurred for the time being I have not used right now. As like all jQuery plugin this plugin also does need jQuery file and there is another .js file given for plugin called ajaxfileupload.js. So I have created a test.aspx to test jQuery file and written following html for that . Upload As you can see in above code there its very simple. I have included the jQuery and ajafileupload.js given by the file upload give and there are three elements that I have used one if plain file input control you can also use the asp.net file upload control and but here I don’t need it so I have user file upload control. There is button there called which is calling a JavaScript function called “ajaxFileUpload” and here we will write a code upload that. There is an image called loading which just an animated gif which will display during the async call of generic handler. Following is code ajaxFileUpload function. As you can see in above code I have putted our generic handler url which will upload the file on server as url parameter. There is also parameter called secureURI is required to be true if you are uploading file through the secure channel and as a third parameter we have to pass a file upload control id which I have already passed and in fourth parameter we have to passed busy indicator which I have also passed. Once we passed all the parameter then it will call a method for plugin and will return response in terms of message and error. So There is two handler function written for that. That’s it. Our async file upload is ready. As you can easily integrate it and also it working fine in all the browser. Hope you like it. Stay tuned for more. Till then happy programming..
December 24, 2011
by Jalpesh Vadgama
· 66,948 Views
article thumbnail
Maven + JavaScript Unit Test: Running in a Continuous Integration Environment
So you're still interested in unit testing JavaScript (good). This post is an extension of my much more indepth first posting on how to unit test JavaScript using JS Test Driver. Please check it out here. Recap Last Posting In the last posting we successfully unit tested JavaScript using Maven and JsTest Driver. This allowes us to test JavaScript when on an environment that has a modern browser installed and can be run. Problem with typical CI environments So what happens when the test are passing on your local box, but you go to check in your code and the Continuous Integration (CI) server pukes on the new tests becasue there is no "screen" to run chrome or firefox? As of this posting, none of the top-tier browsers have a "headless" or an in-memory only browser window. There are alternatives to running JavaScript in a browser, such as rhino.js, env.js or HtmlUnit, however, these are just ports of browsers and the JavaScript and DOM representation are not 100% accurate which can lead to problems with your code when rendered in a client's browser. Approach What we need to do is to run JSTestDriver's browser in a Virtual X Framebuffer (Xvfb) which is possible on nearly all Linux based systems. The example below uses a Solaris version of Linux, however, Debian and RedHat linux distrubutions come with the simplified bash script to easily run an appliation in a virtual framebuffer. This solution was derived from one posted solution on the JS Test Driver wiki. The given example is also a full working example that is in use at my current client. Here is the quick list of what we will accomplish. Note, several of these steps are discussed in depth in the previous post and are not covered in depth here. Create a profile to run Js Unit-Tests Copy JsTestDriver library to a known location for Maven to use Copy JavaScript main and test files to known locations Use ANT to start JsTestDriver and pipe the screen into xvfb Here is a sample profile to use. You will need to adjust the properties at the top of the profile to match your system. ci-jstests /opt/swf/bin/firefox 1.3.2 /opt/X11R6/xvfb-run org.apache.maven.plugins maven-dependency-plugin 2.1 copy generate-resources copy com.google.jstestdriver jstestdriver ${js-test-driver.version} jar true jsTestDriver.jar ${project.build.directory}/jstestdriver false true maven-resources-plugin 2.4.3 copy-main-files generate-test-resources copy-resources ${project.build.directory}/test-classes/main-js src/main/webapp/scripts false copy-test-files generate-test-resources copy-resources ${project.build.directory}/test-classes/test-js src/test/webapp/scripts false org.apache.maven.plugins maven-antrun-plugin 1.6 test run Possible problems Although I cannot predict or fix all problems, I can share the one major problem I ran into with Solaris and the script used to fix that. In Solaris (and could happen to other distros) the xvfb-run script was not available and several of the other libraries did not exist. I first had to download the latest X libraries and place them in their appropriate locations on the CI server. Next, I had to re-engineer the xvfb-run script. Here is a copy of my script (NOTE: This is the solution for my server and this may not work for you) I created a script that contains: /usr/openwin/bin/Xvfb :1 screen 0 1280x1024x8 pixdepths 8 24 fbdir /tmp/.X11-vbf & From http://www.ensor.cc/2011/08/maven-javascript-unit-test-running-in.html
December 23, 2011
by Mike Ensor
· 12,292 Views
article thumbnail
How To Sort String Array Using LINQ In C#
A string[] array and use a LINQ query expression to order its contents alphabetically. Note that we are ordering the strings, not the letters in the strings. using System; using System.Linq; class Program { static void Main() { string[] a = new string[] {"Indonesian","Korean","Japanese","English","German"}; var sort = from s in a orderby s select s; foreach (string c in sort) { Console.WriteLine(c); } } } /*OUTPUT English German Indonesian Japanese Korean */ Eclipse IDE and Eclipse
December 14, 2011
by Snippets Manager
· 10,951 Views · 1 Like
article thumbnail
Magic: The Gathering in JavaScript and HTML5
as a user interface fan, i could not miss the development with html 5. so the goal of this post is to walk through a graphic application that uses javascript and html 5. we will see through examples one way (among others) to develop this kind of project. application overview tools the html 5 page data gathering cards loading & cache handling cards display mouse management state storage animations handling multi-devices conclusion to go further application overview we will produce an application that will let us display a magic the gathering ©(courtesy of www.wizards.com/magic ) cards collection. users will be able to scroll and zoom using the mouse (like bing maps, for example). you can see the final result here: http://bolaslenses.catuhe.com the project source files can be downloaded here: http://www.catuhe.com/msdn/bolaslenses.zip cards are stored on windows azure storage and use the azure content distribution network ( cdn : a service that deploys data near the final users) in order to achieve maximum performances. an asp.net service is used to return cards list (using json format). tools to write our application, we will use visual studio 2010 sp1 with web standards update . this extension adds intellisense support in html 5 page (which is a really important thing ). so, our solution will contain an html 5 page side by side with .js files (these files will contain javascript scripts). about debug, it is possible to set a breakpoint directly in the .js files under visual studio. it is also possible to use the developer bar of internet explorer 9 (use f12 key to display it). debug with visual studio 2010 debug with internet explorer 9 (f12/developer bar) so, we have a modern developer environment with intellisense and debug support. therefore, we are ready to start and first of all, we will write the html 5 page. the html 5 page our page will be built around an html 5 canvas which will be used to draw the cards: cards scanned by mwshq team magic the gathering official site : http://www.wizards.com/magic bolas lenses your browser does not support html5 canvas. loading data... if we dissect this page, we can note that it is divided into two parts: the header part with the title, the logo and the special mentions the main part (section) holds the canvas and the tooltips that will display the status of the application. there is also a hidden image ( backimage ) used as source for not yet loaded cards. to build the layout of the page, a style sheet ( full.css ) is applied. style sheets are a mechanism used to change the tags styles (in html, a style defines the entire display options for a tag): html, body { height: 100%; } body { background-color: #888888; font-size: .85em; font-family: "segoe ui, trebuchet ms" , verdana, helvetica, sans-serif; margin: 0; padding: 0; color: #696969; } a:link { color: #034af3; text-decoration: underline; } a:visited { color: #505abc; } a:hover { color: #1d60ff; text-decoration: none; } a:active { color: #12eb87; } header, footer, nav, section { display: block; } table { width: 100%; } header, #header { position: relative; margin-bottom: 0px; color: #000; padding: 0; } #title { font-weight: bold; color: #fff; border: none; font-size: 60px !important; vertical-align: middle; margin-left: 70px } #legal { text-align: right; color: white; font-size: 14px; width: 50%; position: absolute; top: 15px; right: 10px } #leftheader { width: 50%; vertical-align: middle; } section { margin: 20px 20px 20px 20px; } #maincanvas{ border: 4px solid #000000; } #cardscount { font-weight: bolder; font-size: 1.1em; } .tooltip { position: absolute; bottom: 5px; color: black; background-color: white; margin-right: auto; margin-left: auto; left: 35%; right: 35%; padding: 5px; width: 30%; text-align: center; border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; box-shadow: 2px 2px 2px #333333; } #bolaslogo { width: 64px; height: 64px; } #picturecell { float: left; width: 64px; margin: 5px 5px 5px 5px; vertical-align: middle; } thus, this sheet is responsible for setting up the following display: style sheets are powerful tools that allow an infinite number of displays. however, they are sometimes complicated to setup (for example if a tag is affected by a class, an identifier and its container). to simplify this setup, the development bar of internet explorer 9 is particularly useful because we can use it to see styles hierarchy that is applied to a tag. for example let’s take a look at the waittext tooltip with the development bar. to do this, you must press f12 in internet explorer and use the selector to choose the tooltip: once the selection is done, we can see the styles hierarchy: thus, we can see that our div received its styles from the body tag and the . tooltip entry of the style sheet. with this tool, it becomes possible to see the effect of each style (which can be disabled). it is also possible to add new style on the fly. another important point of this window is the ability to change the rendering mode of internet explorer 9. indeed, we can test how, for example, internet explorer 8 will handle the same page. to do this, go to the [ browser mode ] menu and select the engine of internet explorer 8. this change will especially impact our tooltip as it uses border-radius (rounded edge) and box-shadow that are features of css 3: internet explorer 9 internet explorer 8 our page provides a graceful degradation as it still works (with no annoying visual difference) when the browser does not support all the required technologies. now that our interface is ready, we will take a look at the data source to retrieve the cards to display. the server provides the cards list using json format on this url: http://bolaslenses.catuhe.com/ home/listofcards/?colorstring=0 it takes one parameter ( colorstring ) to select a specific color (0 = all). when developing with javascript, there is a good reflex to have (reflex also good in other languages too, but really important in javascript): one must ask whether what we want to develop has not been already done in an existing framework. indeed, there is a multitude of open source projects around javascript. one of them is jquery which provides a plethora of convenient services. thus, in our case to connect to the url of our server and get the cards list, we could go through a xmlhttprequest and have fun to parse the returned json. or we can use jquery . so we will use the getjson function which will take care of everything for us: function getlistofcards() { var url = "http://bolaslenses.catuhe.com/home/listofcards/?jsoncallback=?"; $.getjson(url, { colorstring: "0" }, function (data) { listofcards = data; $("#cardscount").text(listofcards.length + " cards displayed"); $("#waittext").slidetoggle("fast"); }); } as we can see, our function stores the cards list in the listofcards variable and calls two jquery functions: text that change the text of a tag slidetoggle that hides (or shows) a tag by animating its height the listofcards list contains objects whose format is: id : unique identifier of the card path : relative path of the card (without the extension) it should be noted that the url of the server is called with the “ ?jsoncallback=? ” suffix. indeed, ajax calls are constrained in terms of security to connect only to the same address as the calling script. however, there is a solution called jsonp that will allow us to make a concerted call to the server (which of course must be aware of the operation). and fortunately, jquery can handle it all alone by just adding the right suffix. once we have our cards list, we can set up the pictures loading and caching. cards loading & cache handling the main trick of our application is to draw only the cards effectively visible on the screen. the display window is defined by a zoom level and an offset (x, y) in the overall system. var visucontrol = { zoom : 0.25, offsetx : 0, offsety : 0 }; the overall system is defined by 14819 cards that are spread over 200 columns and 75 rows. also, we must be aware that each card is available in three versions: high definition: 480x680 without compression (.jpg suffix) medium definition: 240x340 with standard compression (.50.jpg suffix) low definition: 120x170 with strong compression (.25.jpg suffix) thus, depending on the zoom level, we will load the correct version to optimize networks transfer. to do this we will develop a function that will give an image for a given card. this function will be configured to download a certain level of quality. in addition it will be linked with lower quality level to return it if the card for the current level is not yet uploaded: function imagecache(substr, replacementcache) { var extension = substr; var backimage = document.getelementbyid("backimage"); this.load = function (card) { var localcache = this; if (this[card.id] != undefined) return; var img = new image(); localcache[card.id] = { image: img, isloaded: false }; currentdownloads++; img.onload = function () { localcache[card.id].isloaded = true; currentdownloads--; }; img.onerror = function() { currentdownloads--; }; img.src = "http://az30809.vo.msecnd.net/" + card.path + extension; }; this.getreplacementfromlowercache = function (card) { if (replacementcache == undefined) return backimage; return replacementcache.getimageforcard(card); }; this.getimageforcard = function(card) { var img; if (this[card.id] == undefined) { this.load(card); img = this.getreplacementfromlowercache(card); } else { if (this[card.id].isloaded) img = this[card.id].image; else img = this.getreplacementfromlowercache(card); } return img; }; } an imagecache is built by giving the associated suffix and the underlying cache. here you can see two important functions: load : this function will load the right picture and will store it in a cache (the msecnd.net url is the azure cdn address of the cards) getimageforcard : this function returns the card picture from the cache if already loaded. otherwise it requests the underlying cache to return its version (and so on) so to handle our 3 levels of caches, we have to declare three variables: var imagescache25 = new imagecache(".25.jpg"); var imagescache50 = new imagecache(".50.jpg", imagescache25); var imagescachefull = new imagecache(".jpg", imagescache50); selecting the right cover is only depending on zoom: function getcorrectimagecache() { if (visucontrol.zoom <= 0.25) return imagescache25; if (visucontrol.zoom <= 0.8) return imagescache50; return imagescachefull; } to give a feedback to the user, we will add a timer that will manage a tooltip that indicates the number of images currently loaded: function updatestats() { var stats = $("#stats"); stats.html(currentdownloads + " card(s) currently downloaded."); if (currentdownloads == 0 && statsvisible) { statsvisible = false; stats.slidetoggle("fast"); } else if (currentdownloads > 1 && !statsvisible) { statsvisible = true; stats.slidetoggle("fast"); } } setinterval(updatestats, 200); again we note the use of jquery to simplify animations. we will now discuss the display of cards. cards display to draw our cards, we need to actually fill the canvas using its 2d context (which exists only if the browser supports html 5 canvas): var maincanvas = document.getelementbyid("maincanvas"); var drawingcontext = maincanvas.getcontext('2d'); the drawing will be made by processlistofcards function (called 60 times per second): function processlistofcards() { if (listofcards == undefined) { drawwaitmessage(); return; } maincanvas.width = document.getelementbyid("center").clientwidth; maincanvas.height = document.getelementbyid("center").clientheight; totalcards = listofcards.length; var localcardwidth = cardwidth * visucontrol.zoom; var localcardheight = cardheight * visucontrol.zoom; var effectivetotalcardsinwidth = colscount * localcardwidth; var rowscount = math.ceil(totalcards / colscount); var effectivetotalcardsinheight = rowscount * localcardheight; initialx = (maincanvas.width - effectivetotalcardsinwidth) / 2.0 - localcardwidth / 2.0; initialy = (maincanvas.height - effectivetotalcardsinheight) / 2.0 - localcardheight / 2.0; // clear clearcanvas(); // computing of the viewing area var initialoffsetx = initialx + visucontrol.offsetx * visucontrol.zoom; var initialoffsety = initialy + visucontrol.offsety * visucontrol.zoom; var startx = math.max(math.floor(-initialoffsetx / localcardwidth) - 1, 0); var starty = math.max(math.floor(-initialoffsety / localcardheight) - 1, 0); var endx = math.min(startx + math.floor((maincanvas.width - initialoffsetx - startx * localcardwidth) / localcardwidth) + 1, colscount); var endy = math.min(starty + math.floor((maincanvas.height - initialoffsety - starty * localcardheight) / localcardheight) + 1, rowscount); // getting current cache var imagecache = getcorrectimagecache(); // render for (var y = starty; y < endy; y++) { for (var x = startx; x < endx; x++) { var localx = x * localcardwidth + initialoffsetx; var localy = y * localcardheight + initialoffsety; // clip if (localx > maincanvas.width) continue; if (localy > maincanvas.height) continue; if (localx + localcardwidth < 0) continue; if (localy + localcardheight < 0) continue; var card = listofcards[x + y * colscount]; if (card == undefined) continue; // get from cache var img = imagecache.getimageforcard(card); // render try { if (img != undefined) drawingcontext.drawimage(img, localx, localy, localcardwidth, localcardheight); } catch (e) { $.grep(listofcards, function (item) { return item.image != img; }); } } }; // scroll bars drawscrollbars(effectivetotalcardsinwidth, effectivetotalcardsinheight, initialoffsetx, initialoffsety); // fps computefps(); } this function is built around many key points: if the cards list is not yet loaded, we display a tooltip indicating that download is in progress: var pointcount = 0; function drawwaitmessage() { pointcount++; if (pointcount > 200) pointcount = 0; var points = ""; for (var index = 0; index < pointcount / 10; index++) points += "."; $("#waittext").html("loading...please wait" + points); subsequently, we define the position of the display window (in terms of cards and coordinates), then we proceed to clean the canvas: function clearcanvas() { maincanvas.width = document.body.clientwidth - 50; maincanvas.height = document.body.clientheight - 140; drawingcontext.fillstyle = "rgb(0, 0, 0)"; drawingcontext.fillrect(0, 0, maincanvas.width, maincanvas.height); } then we browse the cards list and call the drawimage function of the canvas context. the current image is provided by the active cache (depending on the zoom): // get from cache var img = imagecache.getimageforcard(card); // render try { if (img != undefined) drawingcontext.drawimage(img, localx, localy, localcardwidth, localcardheight); } catch (e) { $.grep(listofcards, function (item) { return item.image != img; }); we also have to draw the scroll bar with the roundedrectangle function that uses quadratic curves: function roundedrectangle(x, y, width, height, radius) { drawingcontext.beginpath(); drawingcontext.moveto(x + radius, y); drawingcontext.lineto(x + width - radius, y); drawingcontext.quadraticcurveto(x + width, y, x + width, y + radius); drawingcontext.lineto(x + width, y + height - radius); drawingcontext.quadraticcurveto(x + width, y + height, x + width - radius, y + height); drawingcontext.lineto(x + radius, y + height); drawingcontext.quadraticcurveto(x, y + height, x, y + height - radius); drawingcontext.lineto(x, y + radius); drawingcontext.quadraticcurveto(x, y, x + radius, y); drawingcontext.closepath(); drawingcontext.stroke(); drawingcontext.fill(); } function drawscrollbars(effectivetotalcardsinwidth, effectivetotalcardsinheight, initialoffsetx, initialoffsety) { drawingcontext.fillstyle = "rgba(255, 255, 255, 0.6)"; drawingcontext.linewidth = 2; // vertical var totalscrollheight = effectivetotalcardsinheight + maincanvas.height; var scaleheight = maincanvas.height - 20; var scrollheight = maincanvas.height / totalscrollheight; var scrollstarty = (-initialoffsety + maincanvas.height * 0.5) / totalscrollheight; roundedrectangle(maincanvas.width - 8, scrollstarty * scaleheight + 10, 5, scrollheight * scaleheight, 4); // horizontal var totalscrollwidth = effectivetotalcardsinwidth + maincanvas.width; var scalewidth = maincanvas.width - 20; var scrollwidth = maincanvas.width / totalscrollwidth; var scrollstartx = (-initialoffsetx + maincanvas.width * 0.5) / totalscrollwidth; roundedrectangle(scrollstartx * scalewidth + 10, maincanvas.height - 8, scrollwidth * scalewidth, 5, 4); } and finally, we need to compute the number of frames per second: function computefps() { if (previous.length > 60) { previous.splice(0, 1); } var start = (new date).gettime(); previous.push(start); var sum = 0; for (var id = 0; id < previous.length - 1; id++) { sum += previous[id + 1] - previous[id]; } var diff = 1000.0 / (sum / previous.length); $("#cardscount").text(diff.tofixed() + " fps. " + listofcards.length + " cards displayed"); } drawing cards relies heavily on the browser's ability to speed up canvas rendering. for the record, here are the performances on my machine with the minimum zoom level (0.05): browser fps internet explorer 9 30 firefox 5 30 chrome 12 17 ipad (with a zoom level of 0.8) 7 windows phone mango (with a zoom level of 0.8) 20 (!!) the site even works on mobile phones and tablets as long as they support html 5. here we can see the inner power of html 5 browsers that can handle a full screen of cards more than 30 times per second! mouse management to browse our cards collection, we have to manage the mouse (including its wheel). for the scrolling, we'll just handle the onmouvemove , onmouseup and onmousedown events. onmouseup and onmousedown events will be used to detect if the mouse is clicked or not: var mousedown = 0; document.body.onmousedown = function (e) { mousedown = 1; getmouseposition(e); previousx = posx; previousy = posy; }; document.body.onmouseup = function () { mousedown = 0; }; the onmousemove event is connected to the canvas and used to move the view: var previousx = 0; var previousy = 0; var posx = 0; var posy = 0; function getmouseposition(eventargs) { var e; if (!eventargs) e = window.event; else { e = eventargs; } if (e.offsetx || e.offsety) { posx = e.offsetx; posy = e.offsety; } else if (e.clientx || e.clienty) { posx = e.clientx; posy = e.clienty; } } function onmousemove(e) { if (!mousedown) return; getmouseposition(e); mousemovefunc(posx, posy, previousx, previousy); previousx = posx; previousy = posy; } this function (onmousemove) calculates the current position and provides also the previous value in order to move the offset of the display window: function move(posx, posy, previousx, previousy) { currentaddx = (posx - previousx) / visucontrol.zoom; currentaddy = (posy - previousy) / visucontrol.zoom; } mousehelper.registermousemove(maincanvas, move); note that jquery also provides tools to manage mouse events. for the management of the wheel, we will have to adapt to different browsers that do not behave the same way on this point: function wheel(event) { var delta = 0; if (event.wheeldelta) { delta = event.wheeldelta / 120; if (window.opera) delta = -delta; } else if (event.detail) { /** mozilla case. */ delta = -event.detail / 3; } if (delta) { wheelfunc(delta); } if (event.preventdefault) event.preventdefault(); event.returnvalue = false; } we can see that everyone does what he wants :). the function to register with this event is: mousehelper.registerwheel = function (func) { wheelfunc = func; if (window.addeventlistener) window.addeventlistener('dommousescroll', wheel, false); window.onmousewheel = document.onmousewheel = wheel; }; and we will use this function to change the zoom with the wheel: // mouse mousehelper.registerwheel(function (delta) { currentaddzoom += delta / 500.0; }); finally we will add a bit of inertia when moving the mouse (and the zoom) to give some kind of smoothness: // inertia var inertia = 0.92; var currentaddx = 0; var currentaddy = 0; var currentaddzoom = 0; function doinertia() { visucontrol.offsetx += currentaddx; visucontrol.offsety += currentaddy; visucontrol.zoom += currentaddzoom; var effectivetotalcardsinwidth = colscount * cardwidth; var rowscount = math.ceil(totalcards / colscount); var effectivetotalcardsinheight = rowscount * cardheight var maxoffsetx = effectivetotalcardsinwidth / 2.0; var maxoffsety = effectivetotalcardsinheight / 2.0; if (visucontrol.offsetx < -maxoffsetx + cardwidth) visucontrol.offsetx = -maxoffsetx + cardwidth; else if (visucontrol.offsetx > maxoffsetx) visucontrol.offsetx = maxoffsetx; if (visucontrol.offsety < -maxoffsety + cardheight) visucontrol.offsety = -maxoffsety + cardheight; else if (visucontrol.offsety > maxoffsety) visucontrol.offsety = maxoffsety; if (visucontrol.zoom < 0.05) visucontrol.zoom = 0.05; else if (visucontrol.zoom > 1) visucontrol.zoom = 1; processlistofcards(); currentaddx *= inertia; currentaddy *= inertia; currentaddzoom *= inertia; // epsilon if (math.abs(currentaddx) < 0.001) currentaddx = 0; if (math.abs(currentaddy) < 0.001) currentaddy = 0; } this kind of small function does not cost a lot to implement, but adds a lot to the quality of user experience. state storage also to provide a better user experience, we will save the display window’s position and zoom. to do this, we will use the service of localstorage (which saves pairs of keys / values for the long term (the data is retained after the browser is closed) and only accessible by the current window object): function saveconfig() { if (window.localstorage == undefined) return; // zoom window.localstorage["zoom"] = visucontrol.zoom; // offsets window.localstorage["offsetx"] = visucontrol.offsetx; window.localstorage["offsety"] = visucontrol.offsety; } // restore data if (window.localstorage != undefined) { var storedzoom = window.localstorage["zoom"]; if (storedzoom != undefined) visucontrol.zoom = parsefloat(storedzoom); var storedoffsetx = window.localstorage["offsetx"]; if (storedoffsetx != undefined) visucontrol.offsetx = parsefloat(storedoffsetx); var storedoffsety = window.localstorage["offsety"]; if (storedoffsety != undefined) visucontrol.offsety = parsefloat(storedoffsety); } animations to add even more dynamism to our application we will allow our users to double-click on a card to zoom and focus on it. our system should animate three values: the two offsets (x, y) and the zoom. to do this, we will use a function that will be responsible of animating a variable from a source value to a destination value with a given duration: var animationhelper = function (root, name) { var paramname = name; this.animate = function (current, to, duration) { var offset = (to - current); var ticks = math.floor(duration / 16); var offsetpart = offset / ticks; var tickscount = 0; var intervalid = setinterval(function () { current += offsetpart; root[paramname] = current; tickscount++; if (tickscount == ticks) { clearinterval(intervalid); root[paramname] = to; } }, 16); }; }; the use of this function is: // prepare animations parameters var zoomanimationhelper = new animationhelper(visucontrol, "zoom"); var offsetxanimationhelper = new animationhelper(visucontrol, "offsetx"); var offsetyanimationhelper = new animationhelper(visucontrol, "offsety"); var speed = 1.1 - visucontrol.zoom; zoomanimationhelper.animate(visucontrol.zoom, 1.0, 1000 * speed); offsetxanimationhelper.animate(visucontrol.offsetx, targetoffsetx, 1000 * speed); offsetyanimationhelper.animate(visucontrol.offsety, targetoffsety, 1000 * speed); the advantage of the animationhelper function is that it is able to animate as many parameters as you wish (and that only with the settimer function!) handling multi-devices finally we will ensure that our page can also be seen on tablets pc and even on phones. to do this, we will use a feature of css 3: the media-queries . with this technology, we can apply style sheets according to some queries such as a specific display size: here we see that if the screen width is less than 480 pixels, the following style sheet will be added: #legal { font-size: 8px; } #title { font-size: 30px !important; } #waittext { font-size: 12px; } #bolaslogo { width: 48px; height: 48px; } #picturecell { width: 48px; } finally we will ensure that our page can also be seen on tablets pc and even on phones. to do this, we will use a feature of css 3: #legal { font-size: 8px; } #title { font-size: 30px !important; } #waittext { font-size: 12px; } #bolaslogo { width: 48px; height: 48px; } #picturecell { width: 48px; } conclusion html 5 / css 3 / javascript and visual studio 2010 allow to develop portable and efficient solutions (within the limits of browsers that support html 5 of course) with some great features such as hardware accelerated rendering. this kind of development is also simplified by the use of frameworks like jquery. also, i am especially fan of javascript that turns out to be a very powerful dynamic language. of course, c# or vb.net developers have to change theirs reflexes but for the development of web pages it's worth. in conclusion, i think that the best to be convinced is to try! to go further internet explorer test drive: http://ie.microsoft.com/testdrive/ internet explorer 9 guide for developer : http://msdn.microsoft.com/en-us/ie/ff468705 w3c site for html 5 : http://dev.w3.org/html5/spec/overview.html internet explorer site : http://msdn.microsoft.com/en-us/ie/aa740469 about the author david catuhe is a developer evangelist for microsoft france in charge of user experience development tools (from xaml to directx/xna and html5). he defines himself as a geek and likes coding all that refer to graphics. before working for microsoft, he founded a company that developed a realtime 3d engine written with directx ( www.vertice.fr ). source: http://blogs.msdn.com/b/eternalcoding/archive/2011/07/25/feedback-of-a-graphic-development-using-html5-amp-javascript.aspx
October 24, 2011
by David Catuhe
· 25,164 Views · 1 Like
article thumbnail
Developing with HTML5, CoffeeScript and Twitter's Bootstrap
this article is the fourth in a series about my adventures developing a fitness tracking application with html5, play scala, coffeescript and jade. previous articles can be found at: integrating scalate and jade with play 1.2.3 trying to make coffeescript work with scalate and play integrating html5 boilerplate with scalate and play developing features after getting my desired infrastructure setup, i started coding like a madman. the first feature i needed was a stopwatch to track the duration of a workout, so i started writing one with coffeescript. after spending 20 minutes playing with dates and settimeout, i searched and found a stopwatch jquery plug-in . i added this to my app, deployed it to heroku , brought up the app on my iphone 3g, clicked start and started riding my bike to work. when i arrived, i unlocked my phone and discovered that the time had stopped. at first, i thought this was a major setback. my disappointed disappeared when i found a super neat javascript stopwatch and kåre byberg's version that worked just fine. this stopwatch used settimeout, so by keeping the start time, the app on the phone would catch up as soon as you unlocked it. i ported kåre's script to coffeescript and rejoiced in my working stopwatch. # created by kåre byberg © 21.01.2005. please acknowledge if used # on other domains than http://www.timpelen.com. # ported to coffeescript by matt raible. also added hours support. flagclock = 0 flagstop = 0 stoptime = 0 refresh = null clock = null start = (button, display) -> clock = display startdate = new date() starttime = startdate.gettime() if flagclock == 0 $(button).html("stop") flagclock = 1 counter starttime, display else $(button).html("start") flagclock = 0 flagstop = 1 counter = (starttime) -> currenttime = new date() timediff = currenttime.gettime() - starttime timediff = timediff + stoptime if flagstop == 1 if flagclock == 1 $(clock).val formattime timediff, "" callback = -> counter starttime refresh = settimeout callback, 10 else window.cleartimeout refresh stoptime = timediff formattime = (rawtime, roundtype) -> if roundtype == "round" ds = math.round(rawtime / 100) + "" else ds = math.floor(rawtime / 100) + "" sec = math.floor(rawtime / 1000) min = math.floor(rawtime / 60000) hour = math.floor(rawtime / 3600000) ds = ds.charat(ds.length - 1) start() if hour >= 24 sec = sec - 60 * min + "" sec = prependzerocheck sec min = min - 60 * hour + "" min = prependzerocheck min hour = prependzerocheck hour hour + ":" + min + ":" + sec + "." + ds prependzerocheck = (time) -> time = time + "" # convert from int to string unless time.charat(time.length - 2) == "" time = time.charat(time.length - 2) + time.charat(time.length - 1) else time = 0 + time.charat(time.length - 1) reset = -> flagstop = 0 stoptime = 0 window.cleartimeout refresh if flagclock == 1 resetdate = new date() resettime = resetdate.gettime() counter resettime else $(clock).val "00:00:00.0" @stopwatch = { start: start reset: reset } the scalate/jade template to render this stopwatch looks as follows: script(type="text/javascript" src={uri("/public/javascripts/stopwatch.coffee")}) #display input(id="clock" class="xlarge" type="text" value="00:00:00.0" readonly="readonly") #controls button(id="start" type="button" class="btn primary") start button(id="reset" type="button" class="btn :disabled") reset :plain next, i wanted to create a map that would show your location. for this, i used merge design's html 5 geolocation demo as a guide. the html5 geo api is pretty simple, containing only three methods: // gets the users current position navigator.geolocation.getcurrentposition(successcallback, errorcallback, options); // request repeated updates of position watchid = navigator.geolocation.watchposition(successcallback, errorcallback); // cancel the updates navigator.geolocation.clearwatch(watchid); after rewriting the geolocation example in coffeescript, i ended up with the following code in my map.coffee script. you'll notice it uses google maps javascript api to show an actual map with a marker. # geolocation with html 5 and google maps api based on example from maxheapsize: # http://maxheapsize.com/2009/04/11/getting-the-browsers-geolocation-with-html-5/ # this script is by merge database and design, http://merged.ca/ -- if you use some, # all, or any of this code, please offer a return link. map = null mapcenter = null geocoder = null latlng = null timeoutid = null initialize = -> if modernizr.geolocation navigator.geolocation.getcurrentposition showmap showmap = (position) -> latitude = position.coords.latitude longitude = position.coords.longitude mapoptions = { zoom: 15, maptypeid: google.maps.maptypeid.roadmap } map = new google.maps.map(document.getelementbyid("map"), mapoptions) latlng = new google.maps.latlng(latitude, longitude) map.setcenter(latlng) geocoder = new google.maps.geocoder() geocoder.geocode({'latlng': latlng}, addaddresstomap) addaddresstomap = (results, status) -> if (status == google.maps.geocoderstatus.ok) if (results[1]) marker = new google.maps.marker({ position: latlng, map: map }) $('#location').html('your location: ' + results[0].formatted_address) else alert "sorry, we were unable to geocode that address." start = -> timeoutid = settimeout initialize, 500 reset = -> if (timeoutid) cleartimeout timeoutid @map = { start: start reset: reset } the template to show the map is a mere 20 lines of jade: script(type="text/javascript" src="http://www.google.com/jsapi") script(type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false") :css .demo-map { border: 1px solid silver; height: 200px; margin: 10px auto; width: 280px; } #map(class="demo-map") p(id="location") span(class="label success") new | fetching your location with html 5 geolocation... script(type="text/javascript" src={uri("/public/javascripts/map.coffee")}) :javascript map.start(); the last two features i wanted were 1) distance traveled and 2) drawing the route taken on the map. for this i learned from a simple trip meter using the geolocation api . as i was beginning to port the js to coffeescript, i thought, "there's got to be a better way." i searched and found js2coffee to do most of the conversion for me. if you know javascript and you're learning coffeescript, this is an invaluable tool. i tried out the trip meter that night evening on a bike ride and noticed it said i'd traveled 3 miles when i'd really gone 6. i quickly figured out it was only calculating start point to end point and not taking into account all the turns in between. to view what was happening, i integrated my odometer.coffee with my map using google maps polylines . upon finishing the integration, i discovered two things, 1) html5 geolocation was highly inaccurate and 2) geolocation doesn't run in the background . i was able to solve the first problem by passing in {enablehighaccuracy: true} to navigator.geolocation.watchposition(). below are two screenshots showing before high accuracy and after. both screenshots are from the same two-block walk. the second issue is a slight show-stopper. phonegap might be able to solve the problem, but i'm currently using a workaround → turning off auto-lock and keeping safari in the foreground. making it look good after i got all my desired features developed, i moved onto making the app look good. i started by using sass for my css and installed play's sass module . i then switched to less when i discovered and added twitter's bootstrap to my project. at first i used play's less module (version 0.3), but ran into compilation issues . i then tried play's greenscript module , but gave up on it when i found it was incompatible with the coffeescript module . switching back to the less module and using the "0.3.compatibility" version solved all remaining issues. you might remember that i integrated html5 boilerplate and wondering why i have both bootstrap and boilerplate in my project. at this point, i don't think boilerplate is needed, but i've kept it just in case it's doing something for html5 cross-browser compatibility. i've renamed its style.css to style.less and added the following so it has access to bootstrap's variables. /* variables from bootstrap */ @import "libs/variables.less"; then i made my app look a lot better with layouts, stylish forms , a fixed topbar and alerts . for example, here's the coffeescript i wrote to display geolocation errors: geolocationerror = (error) -> msg = 'unable to locate position. ' switch error.code when error.timeout then msg += 'timeout.' when error.position_unavailable then msg += 'position unavailable.' when error.permission_denied then msg += 'please turn on location services.' when error.unknown_error then msg += error.code $('.alert-message').remove() alert = $('') alert.html('×' + msg); alert.insertbefore($('.span10')) then i set about styling up the app so it looked good on a smartphone with css3 media queries . below is the less code i used to hide elements and squish the widths for smaller devices. @media all and (max-device-width: 480px) { /* hide scrollbar on mobile */ html { overflow-y:hidden } /* hide sidebar on mobile */ .home .span4, .home .page-header, .topbar form { display: none } .home .container { width: 320px; } .about { .container, .span10 { width: 280px; } .span10 { padding-top: 0px; } } tools in the process of developing a stopwatch, odometer, displaying routes and making everything look good, i used a number of tools. i started out primarily with textmate and its bundles for less , coffeescript and jade . when i started writing more scala, i installed the scala textmate bundle . when i needed some debugging, i switched to intellij and installed its scala plugin. coffeescript, less and haml plugins (for jade) were already installed by default. i also used james ward's setup play framework with scala in intellij . issues i think it's obvious that my biggest issue so far is the fact that a webapp can't multitask in the background like a native app can. beyond that, there's accuracy issues with html5's geolocation that i haven't seen in native apps. i also ran into a caching issue when calling getcurrentposition(). it only worked the first time and i had to refresh my browser to get it to work again. strangely enough, this only happened on my desktop (in safari and firefox) and worked fine on my iphone. unfortunately, it looks like phonegap has issues similar to this. my workaround for no webapp multitasking is turning off auto-lock and leaving the browser in the foreground while i exercise. the downside to this is it really drains the battery quickly (~ 3 hours). i constantly have to charge my phone if i'm testing it throughout the day. the testing is a real pain too. i have to deploy to heroku (which is easy enough), then go on a walk or bike ride. if something's broke, i have to return home, tweak some things, redeploy and go again. also, there's been a few times where safari crashes halfway through and i lose all the tracking data. this happens with native apps too, but seemingly not as often. if you'd like to try the app on your mobile phone and see if you experience these issues, checkout play-more.com . summary going forward, there's still more html5 features i'd like to use. in particular, i'd like to play music while the fitness tracker is running. i'd love it if cloud music services (e.g. pandora or spotify) had an api i could use to play music in a webapp. soundcloud might be an option, but i've also thought of just uploading some mp3s and playing them with the tag. i've really enjoyed developing with all these technologies and haven't experienced much frustration so far. the majority has come from integrating scalate into play, but i've resolved most problems. next, i'll talk about how i've improved play's scalate support and my experience working with anorm . source: http://raibledesigns.com/rd/entry/developing_with_html5_coffeescript_and
October 21, 2011
by Matt Raible
· 17,442 Views · 1 Like
article thumbnail
Intercepting onclick event in JavaScript using JQuery
Let’s say you are using some external components in your web page that renders a button as below: The above code will call the delete() method when user clicks on the button. But, what if you want to show a confirmation box before calling the delete()? Since the code is rendered by a external component, most probably you won’t be having control over how its code generated. So, you have to intercept the onclick event and block it until your method is called and then invoke the original method. Lets do it.. var btn = $("#btn"); btn.data("funcToCall", btn.attr("onclick")); $("#btn").removeAttr("onclick"); $("#btn").bind("click", function(e){ if(confirm("Are you sure?")){ var func = $(this).data("funcToCall"); eval(func); } }); As you can see, the onclick function is first stored into that element and then the onclick attribute is removed. Finally when the button in clicked, our custom method is called first and based on the user decision, the delete() method is either called or not called. From http://veerasundar.com/blog/2011/10/intercepting-onclick-event-in-javascript-using-jquery/
October 14, 2011
by Veera Sundar
· 10,809 Views
article thumbnail
Jquery and ASP.NET- Set and Get Value of Server control
Yesterday one of my reader asked me one question that How can I set or get values from Jquery of server side element for example. So I decided to write blog post for this. This blog post is for all this people who are learning Jquery and don’t know how to set or get value for a server like ASP.NET Textbox. I know most of people know about it as Jquery is very popular browser JavaScript framework. I believe jquery as framework because it’s a single file which has lots of functionality. For this I am going to take one simple example asp.net page which contain two textboxes txtName and txtCopyName and button called copyname. On click of that button it will get the value from txtName textbox and set value of another box. So following is HTML for this. As you can see in following code there are two textbox and one button which will call JavaScript function called to CopyName to copy text from one textbox from another textbox.Now we are going to use the Jquery for this. So first we need to include Jquery script file to accomplish the task. So I am going link that jquery.js file in my header section like following. Here I have used the ASP.NET Jquery CDN. If you want know more about Jquery CDN you can visit this link. http://www.asp.net/ajaxlibrary/cdn.ashx Now it’s time to write query code. Here I have used val function to set and get value for the element. Following is the code for CopyName function. function CopyName() { var name = $("#").val(); //get value $("#").val(name); //set value return false; } Here I have used val function of jquery to set and get value. As you can see in the above code, In first statement I have get value in name variable and in another statement it was set to txtCopy textbox. Some people might argue why you have used that ClientID but it’s a good practice to have that because when you use multiple user controls your id and client id will be different. From this I have came to know that there are lots of people still there who does not basic Jquery things so in future I am going to post more post on jquery basics.That’s it. Hope you like it.
September 8, 2011
by Jalpesh Vadgama
· 42,337 Views
article thumbnail
Java NIO vs. IO
when studying both the java nio and io api's, a question quickly pops into mind: when should i use io and when should i use nio? in this text i will try to shed some light on the differences between java nio and io, their use cases, and how they affect the design of your code. main differences of java nio and io the table below summarizes the main differences between java nio and io. i will get into more detail about each difference in the sections following the table. io nio stream oriented buffer oriented blocking io non blocking io selectors stream oriented vs. buffer oriented the first big difference between java nio and io is that io is stream oriented, where nio is buffer oriented. so, what does that mean? java io being stream oriented means that you read one or more bytes at a time, from a stream. what you do with the read bytes is up to you. they are not cached anywhere. furthermore, you cannot move forth and back in the data in a stream. if you need to move forth and back in the data read from a stream, you will need to cache it in a buffer first. java nio's buffer oriented approach is slightly different. data is read into a buffer from which it is later processed. you can move forth and back in the buffer as you need to. this gives you a bit more flexibility during processing. however, you also need to check if the buffer contains all the data you need in order to fully process it. and, you need to make sure that when reading more data into the buffer, you do not overwrite data in the buffer you have not yet processed. blocking vs. non-blocking io java io's various streams are blocking. that means, that when a thread invokes a read() or write(), that thread is blocked until there is some data to read, or the data is fully written. the thread can do nothing else in the meantime. java nio's non-blocking mode enables a thread to request reading data from a channel, and only get what is currently available, or nothing at all, if no data is currently available. rather than remain blocked until data becomes available for reading, the thread can go on with something else. the same is true for non-blocking writing. a thread can request that some data be written to a channel, but not wait for it to be fully written. the thread can then go on and do something else in the mean time. what threads spend their idle time on when not blocked in io calls, is usually performing io on other channels in the meantime. that is, a single thread can now manage multiple channels of input and output. selectors java nio's selectors allow a single thread to monitor multiple channels of input. you can register multiple channels with a selector, then use a single thread to "select" the channels that have input available for processing, or select the channels that are ready for writing. this selector mechanism makes it easy for a single thread to manage multiple channels. how nio and io influences application design whether you choose nio or io as your io toolkit may impact the following aspects of your application design: the api calls to the nio or io classes. the processing of data. the number of thread used to process the data. the api calls of course the api calls when using nio look different than when using io. this is no surprise. rather than just read the data byte for byte from e.g. an inputstream, the data must first be read into a buffer, and then be processed from there. the processing of data the processing of the data is also affected when using a pure nio design, vs. an io design. in an io design you read the data byte for byte from an inputstream or a reader. imagine you were processing a stream of line based textual data. for instance: name: anna age: 25 email: [email protected] phone: 1234567890 this stream of text lines could be processed like this: inputstream input = ... ; // get the inputstream from the client socket bufferedreader reader = new bufferedreader(new inputstreamreader(input)); string nameline = reader.readline(); string ageline = reader.readline(); string emailline = reader.readline(); string phoneline = reader.readline(); notice how the processing state is determined by how far the program has executed. in other words, once the first reader.readline() method returns, you know for sure that a full line of text has been read. the readline() blocks until a full line is read, that's why. you also know that this line contains the name. similarly, when the second readline() call returns, you know that this line contains the age etc. as you can see, the program progresses only when there is new data to read, and for each step you know what that data is. once the executing thread have progressed past reading a certain piece of data in the code, the thread is not going backwards in the data (mostly not). this principle is also illustrated in this diagram: java io: reading data from a blocking stream. a nio implementation would look different. here is a simplified example: bytebuffer buffer = bytebuffer.allocate(48); int bytesread = inchannel.read(buffer); notice the second line which reads bytes from the channel into the bytebuffer. when that method call returns you don't know if all the data you need is inside the buffer. all you know is that the buffer contains some bytes. this makes processing somewhat harder. imagine if, after the first read(buffer) call, that all what was read into the buffer was half a line. for instance, "name: an". can you process that data? not really. you need to wait until at leas a full line of data has been into the buffer, before it makes sense to process any of the data at all. so how do you know if the buffer contains enough data for it to make sense to be processed? well, you don't. the only way to find out, is to look at the data in the buffer. the result is, that you may have to inspect the data in the buffer several times before you know if all the data is inthere. this is both inefficient, and can become messy in terms of program design. for instance: bytebuffer buffer = bytebuffer.allocate(48); int bytesread = inchannel.read(buffer); while(! bufferfull(bytesread) ) { bytesread = inchannel.read(buffer); } the bufferfull() method has to keep track of how much data is read into the buffer, and return either true or false, depending on whether the buffer is full. in other words, if the buffer is ready for processing, it is considered full. the bufferfull() method scans through the buffer, but must leave the buffer in the same state as before the bufferfull() method was called. if not, the next data read into the buffer might not be read in at the correct location. this is not impossible, but it is yet another issue to watch out for. if the buffer is full, it can be processed. if it is not full, you might be able to partially process whatever data is there, if that makes sense in your particular case. in many cases it doesn't. the is-data-in-buffer-ready loop is illustrated in this diagram: java nio: reading data from a channel until all needed data is in buffer. summary nio allows you to manage multiple channels (network connections or files) using only a single (or few) threads, but the cost is that parsing the data might be somewhat more complicated than when reading data from a blocking stream. if you need to manage thousands of open connections simultanously, which each only send a little data, for instance a chat server, implementing the server in nio is probably an advantage. similarly, if you need to keep a lot of open connections to other computers, e.g. in a p2p network, using a single thread to manage all of your outbound connections might be an advantage. this one thread, multiple connections design is illustrated in this diagram: java nio: a single thread managing multiple connections. if you have fewer connections with very high bandwidth, sending a lot of data at a time, perhaps a classic io server implementation might be the best fit. this diagram illustrates a classic io server design: java io: a classic io server design - one connection handled by one thread. from http://tutorials.jenkov.com/java-nio/nio-vs-io.html
August 28, 2011
by Jakob Jenkov
· 134,014 Views · 19 Likes
article thumbnail
An introduction to JSDoc
JSDoc is the de facto standard for documenting JavaScript code. You need to know at least its syntax (which is also used by many other tools) if you publish code. Alas, documentation is still scarce, but this post can help – it shows you how to run JSDoc and how its syntax works. (The JSDoc wiki [2] is the main source of this post, some examples are borrowed from it.) As a tool, JSDoc takes JavaScript code with special /** */ comments and produces HTML documentation for it. For example: Given the following code. /** @namespace */ var util = { /** * Repeat str several times. * @param {string} str The string to repeat. * @param {number} [times=1] How many times to repeat the string. * @returns {string} */ repeat: function(str, times) { if (times === undefined || times < 1) { times = 1; } return new Array(times+1).join(str); } }; The generated HTML looks as follows in a web browser: This post begins with a quick start, so can try out JSDoc immediately if you are impatient. Afterwards, more background information is given. 1. Quick start For the steps described below, you need to have Java installed. JSDoc includes the shell script jsrun.sh that requires Unix (including OS X and Linux) to run. But it should be easy to translate that script to a Windows batch file. Download the latest jsdoc_toolkit. Unpack the archive into, say, $HOME/jsdoc-toolkit. Make the script $HOME/jsdoc-toolkit/jsrun.sh executable and tell it where to look for the JSDoc binary and the template (which controls what the result looks like). JSDOCDIR="$HOME/local/jsdoc-toolkit" JSDOCTEMPLATEDIR="$JSDOCDIR/templates/jsdoc" Now you can move the script anywhere you want to, e.g. a bin/ directory. For the purpose of this demonstration, we don’t move the script. Use jsrun.sh on a directory of JavaScript files: $HOME/jsdoc-toolkit/jsrun.sh -d=$HOME/doc $HOME/js Input: $HOME/js – a directory of JavaScript files (see below for an example). Output: $HOME/doc – where to write the generated files. If you put the JavaScript code at the beginning of this post into a file $HOME/js/util.js then JSDoc produces the following files: $HOME/doc +-- files.html +-- index.html +-- symbols +-- _global_.html +-- src ¦ +-- util.js.html +-- util.html 2. Introduction: What is JSDoc? It’s a common programming problem: You have written JavaScript code that is to be used by others and need a nice-looking HTML documentation of its API. Java has pioneered this domain via its JavaDoc tool. The quasi-standard in the JavaScript world is JSDoc. As seen above, you document an entity by putting before it a special comment that starts with two asterisks. Templates. In order to output anything, JSDoc always needs a template, a mix of JavaScript and specially marked-up HTML that tells it how to translate the parsed documentation to HTML. JSDoc comes with a built-in template, but there are others that you can download [3]. 2.1. Terminology and conventions of JSDoc Doclet: JSDoc calls its comments doclets which clashes with JavaDoc terminology where such comments are called doc comments and a doclet is similar to a JSDoc template, but written in Java. Variable: The term variable in JSDoc often refers to all documentable entities which include global variables, object properties, and inner members. Instance properties: In JavaScript one typically puts methods into a prototype to share them with all instances of a class, while fields (non-function-valued properties) are put into each instance. JSDoc conflates shared properties and per-instance properties and calls them instance properties. Class properties, static properties: are properties of classes, usually of constructor functions. For example, Object.create is a class property of Object. Inner members: An inner member is data nested inside a function. Most relevant for documentation is instance-private data nested inside a constructor function. function MyClass() { var privateCounter = 0; // an inner member this.inc = function() { // an instance property privateCounter++; }; } 2.2. Syntax Let’s review the comment shown at the beginning: /** * Repeat str several times. * @param {string} str The string to repeat. * @param {number} [times=1] How many times to repeat the string. * @returns {string} */ This demonstrates some of the JSDoc syntax which consists of the following pieces. JSDoc comment: is a JavaScript block comment whose first character is an asterisk. This creates the illusion that the token /** starts such a comment. Tags: Comments are structured by starting lines with tags, keywords that are prefixed with an @ symbol. @param is an example above. HTML: You can freely use HTML in JSDoc comments; for example, to display a word in a monospaced font. Type annotations: You can document the type of a value by putting the type name in braces after the appropriate tags. Variations: Single type: @param {string} name Multiple types: @param {string|number} idCode Arrays of a type: @param {string[]} names Name paths: are used to refer to variables inside JSDoc comments. The syntax of such paths is as follows. myFunction MyConstructor MyConstructor.classProperty MyConstructor#instanceProperty MyConstructor-innerMember 2.3. A word on types There are two kinds of values in JavaScript: primitives and objects [7]. Primitive types: boolean, number, string. The values undefined and null are also considered primitive. Object types: All other types are object types, including arrays and functions. Watch out: the names of primitive types start with a lowercase letter. Each primitive type has a corresponding wrapper type, an object type with a capital name whose instances are objects: The wrapper type of boolean is Boolean. The wrapper type of number is Number. The wrapper type of string is String. Getting the name of the type of a value: Primitive value p: via typeof p. > typeof "" 'string' Compare: an instance of the wrapper type is an object. > typeof new String() 'object' Object value o: via o.constructor.name. Example: > new String().constructor.name 'String' 3. Basic tags Meta-data: @fileOverview: marks a JSDoc comment that describes the whole file. @author: Who has written the variable being documented? @deprecated: indicates that the variable is not supported, any more. It is a good practice to document what to use instead. @example: contains a code example, illustrating how the given entity should be used. /** * @example * var str = "abc"; * console.log(repeat(str, 3)); // abcabcabc */ Linking: @see: points to a related resource. /** * @see MyClass#myInstanceMethod * @see The Example Project. */ {@link ...}: works like @see, but can be used inside other tags. @requires resourceDescription: a resource that the documented entity needs. The resource description is either a name path or a natural language description. Versioning: @version versionNumber: indicates the version of the documented entity. Example: @version 10.3.1 @since versionNumber: indicates since which version the documented entity has been available. Example: @since 10.2.0 4. Documenting functions and methods For functions and methods, one can document parameters, return values, and exceptions they might throw. @param {paramType} paramName description: describes the parameter whose name is paramName. Type and description are optional. Examples: @param str @param str The string to repeat. @param {string} str @param {string} str The string to repeat. Advanced features: Optional parameter: @param {number} [times] The number of times is optional. Optional parameter with default value: @param {number} [times=1] The number of times is optional. @returns {returnType} description: describes the return value of the function or method. Either type or description can be omitted. @throws {exceptionType} description: describes an exception that might be thrown during the execution of the function or method. Either type or description can be omitted. 4.1. Inline type information (“inline doc comments”) There are two ways of providing type information for parameters and return values. First, you can add a type annotation to @param and @returns. /** * @param {String} name * @returns {Object} */ function getPerson(name) { } Second, you can inline the type information: function getPerson(/**String*/ name) /**Object*/ { } 5. Documenting variables and fields Fields are properties with non-function values. Because instance fields are often created inside a constructor, you have to document them there. @type {typeName}: What type does the documented variable have? Example: /** @constructor */ function Car(make, owner) { /** @type {string} */ this.make = make; /** @type {Person} */ this.owner = owner; } @type {Person} This tag can also be used to document the return type of functions, but @returns is preferable in this case. @constant: A flag that indicates that the documented variable has a constant value. @default defaultValue: What is the default value of a variable? Example: /** @constructor */ function Page(title) { /** * @default "Untitled" */ this.title = title || "Untitled"; } @property {propType} propName description: Document an instance property in the class comment. Example: /** * @class * @property {string} name The name of the person. */ function Person(name) { this.name = name; } Without this tag, instance properties are documented as follows. /** * @class */ function Person(name) { /** * The name of the person. * @type {string} */ this.name = name; } Which one of those styles to use is a matter of taste. @property does introduce redundancies, though. 6. Documenting classes JavaScript’s built-in means for defining classes are weak, which is why there are many APIs that help with this task [5]. These APIs differ, often radically, so you have to help JSDoc with figuring out what is going on. There are three basic ways of defining a class: Constructor function: You must mark a constructor function, otherwise it will not be documented as a class. That is, capitalization alone does not mark a function as a constructor. /** * @constructor */ function Person(name) { } @class is a synonym for @constructor, but it also allows you to describe the class – as opposed to the function setting up an instance (see tag documentation below for an example). API call and object literal: You need two markers. First, you need to tell JSDoc that a given variable holds a class. Second, you need to mark an object literal as defining a class. The latter is done via the @lends tag. /** @class */ var Person = makeClass( /** @lends Person# */ { say: function(message) { return "This person says: " + message; } } ); API call and object literal with a constructor method: If one of the methods in an object literal performs the task of a constructor (setting up instance data, [8]), you need to mark it as such so that fields are found by JSDoc. Then the documentation of the class moves to that method. var Person = makeClass( /** @lends Person# */ { /** * A class for managing persons. * @constructs */ initialize: function(name) { this.name = name; }, say: function(message) { return this.name + " says: " + message; } } ); Tags: @constructor: marks a function as a constructor. @class: marks a variable as a class or a function as a constructor. Can be used in a constructor comment to separate the description of the constructor (first line below) from the description of the class (second line below). /** * Creates a new instance of class Person. * @class Represents a person. */ Person = function() { } @constructs: marks a method in an object literal as taking up the duties of a constructor. That is, setting up instance data. In such a case, the class must be documented there. Works in tandem with @lends. @lends namePath: specifies to which class the following object literal contributes. There are two ways of contributing. @lends Person# – the object literal contributes instance properties to Person. @lends Person – the object literal contributes class properties to Person. 6.1. Inheritance, namespacing JavaScript has no simple support for subclassing and no real namespaces [6]. You thus have to help JSDoc see what is going on when you are using work-arounds. @extends namePath: indicates that the documented class is the subclass of another one. Example: /** * @constructor * @extends Person */ function Programmer(name) { Person.call(this, name); ... } // Remaining code for subclassing omitted @augments: a synonym for @extends. @namespace: One can use objects to simulate namespaces in JavaScript. This tag marks such objects. Example: /** @namespace */ var util = { ... }; 7. Meta-tags Meta-tags are tags that are added to several variables. You put them in a comment that starts with “/**#@+”. They are then added to all variables until JSDoc encounters the closing comment “/**#@-*/”. Example: /**#@+ * @private * @memberOf Foo */ function baz() {} function zop() {} function pez() {} /**#@-*/ 8. Rarely used tags @ignore: ignore a variable. Note that variables without /** comments are ignored, anyway. @borrows otherNamePath as this.propName: A variable is just a reference to somewhere else; it is documented there. Example: /** * @constructor * @borrows Remote#transfer as this.send */ function SpecialWriter() { this.send = Remote.prototype.transfer; } @description text: Provide a description, the same as all of the text before the first tag. Manual categorization. Sometimes JSDoc misinterprets what a variable is. Then you can help it via one of the following tags: Tag Mark variable as @function function @field non-function value @public public (especially inner variables) @private private @inner inner and thus also private @static accessible without instantiation Name and membership: @name namePath: override the parsed name and use the given name, instead. @memberOf parentNamePath: the documented variable is a member of the specified object. Not explained here: @event, see [2]. 9. Related reading jsdoc-toolkit - A documentation generator for JavaScript: JSDoc homepage on Google Code. Includes a link to the downloads. JSDoc wiki: the official documentation of JSDoc and source of this post. JSDoc wiki – TemplateGallery: lists available JSDoc templates. JSDoc wiki – TagReference: a handy cheat-sheet for JSDoc tags. Lightweight JavaScript inheritance APIs Modules and namespaces in JavaScript JavaScript values: not everything is an object Prototypes as classes – an introduction to JavaScript inheritance From http://www.2ality.com/2011/08/jsdoc-intro.html
August 18, 2011
by Axel Rauschmayer
· 70,835 Views · 2 Likes
article thumbnail
Serialize only specific class properties to JSON string using JavaScriptSerializer
About one year ago I wrote a blog post about JavaScriptSerializer and the Serialize and Deserialize methods it supports. Note: This blog post has been in draft for sometime now, so I decided to complete it and publish it. There might be situation when you want to serialize to JSON string only specific properties of a given class. You can do that using JavaScriptSerializer in combination with LINQ. Let’s say we have the following class definition public class Customer { public string Name { get; set; } public string Surname { get; set; } public string Email { get; set; } public int Age { get; set; } public bool Drinker { get; set; } public bool Smoker { get; set; } public bool Single { get; set; } } Next, lets create method that will create sample data for our demo private List GetListOfCustomers() { List customers = new List(); customers.Add(new Customer() { Name = "Hajan", Surname = "Selmani", Age = 25, Drinker = false, Smoker = false, Single = false, Email = "[email protected]" }); customers.Add(new Customer() { Name = "John", Surname = "Doe", Age = 29, Drinker = false, Smoker = true, Single = false, Email = "[email protected]" }); customers.Add(new Customer() { Name = "Mark", Surname = "Moris", Age = 34, Drinker = true, Smoker = true, Single = true, Email = "[email protected]" }); return customers; } So, we have three customers with some property values for each of them. Now, lets serialize some of their properties using JavaScriptSerializer. First, you must put the following directive: using System.Web.Script.Serialization; Next, we create list of customers that will get the returned value from GetListOfCustomers method and we create instance of JavaScriptSerializer class List customers = GetListOfCustomers(); JavaScriptSerializer serializer = new JavaScriptSerializer(); Now, lets say we want to serialize as JSON string and retrieve only the Age property data… We do that with only one simple line of code: //this will serialize only the 'Age' property string jsonString = serializer.Serialize(customers.Select(x => x.Age)); The result will be: Nice! Now, what if we want to serialize multiple properties at once, but not all class properties? string jsonStringMultiple = serializer.Serialize(customers.Select(x => new { x.Name, x.Surname, x.Age })); The result will be: You see, the result is an array of objects with the four properties and their corresponding values we have selected using the LINQ query above. You can see that integer and boolean values are without quotes, which is correct way of serialization. Now, you probably saw a difference somewhere? Namely, in the first example where we have selected only one property, there are only the values of the property (no property name), while in the second example we have the property name and it’s corresponding value… Why is it like that? It’s because in the second query, we use new { … } to specify multiple properties in the select statement. Therefore, the anonymous new { … } creates an object of each found item. So, if you are interested to make some more tests, run the following two lines of code: var customers1 = customers.Select(x => x.Name).ToList(); var customers2 = customers.Select(x=> new { x.Name } ).ToList(); and you will obviously see the difference. If we use the new { } way for single property selection, like in the following example string jsonString2 = serializer.Serialize(customers.Select(x => new { x.Age })); the result will be: The complete demo code used for this blog post: List customers = GetListOfCustomers(); JavaScriptSerializer serializer = new JavaScriptSerializer(); //this will serialize only the 'Age' property string jsonString = serializer.Serialize(customers.Select(x => x.Age )); string jsonStringMultiple = serializer.Serialize(customers.Select(x => new { x.Name, x.Surname, x.Age, x.Drinker })); var customers1 = customers.Select(x => x.Name).ToList(); var customers2 = customers.Select(x=> new { x.Name } ).ToList(); string jsonString2 = serializer.Serialize(customers.Select(x => new { x.Age })); You can download the demo project here.
August 10, 2011
by Hajan Selmani
· 32,229 Views
  • Previous
  • ...
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×