If you're interested in functional programming, you might also want to checkout my second blog which i'm actively working on!!

Tuesday, May 10, 2016

A new blog is born

I want to thank everyone who took the time reading one or more of my blog posts. This will be my latest blog over here as I started a new blog which is reachable at http://pelssersconsultancy.github.io/

Thursday, May 7, 2015

Switching between maven settings.xml

Often you have to copy the maven settings.xml file which is configured for a specific customer. But while developing in my spare time I just want to use my own settings.xml file. The easiest way to switch to using a different file is shown below:

mvn -gs $M2_HOME/conf/settings_pelssers.xml clean install

Thursday, April 9, 2015

Using ssh tunnel with port forwarding

Connectivity has been setup from our staging environment to the third party server (endpoint of our soap clients). However, I wanted to connect locally with SOAP UI to this server, so I needed to setup an ssh tunnel with portforwarding on my macbook. I used to do this with putty on windows in the past so it took me a bit longer to figure this out.

Let's say the endpoint used from our staging environment would be "http://3rdpartyhostname/coolservice". In this case I want to listen on port 8877, and forward traffic from this port using the ssh tunnel to 3rdpartyhostname on port 80

ssh -f username@staginghostname -L 8877:3rdpartyhostname:80 -N

Now I can connect in SOAPUI to the following endpoint "http://localhost:8877/coolservice"

Thursday, March 26, 2015

Fixing collisions ObjectFactory while executing wsdl2java

Often you have to deal with WSDL's from third parties. Sometimes the WSDL including referenced schemas are setup crappy and you run into issues while converting the WSDL to Java. Below we will look into how to fix these issues.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pelssers</groupId>
<artifactId>objectfactory</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<cxf.version>2.7.8</cxf.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>clean generate-sources install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/helloworld.wsdl</wsdl>
<extraargs>
<extraarg>-frontend</extraarg>
<extraarg>jaxws21</extraarg>
<extraarg>-p</extraarg>
<extraarg>http://com.pelssers.helloworld/=com.pelssers.helloworld</extraarg>
<extraarg>-p</extraarg>
<extraarg>http://com.pelssers.helloworld/wrapper=com.pelssers.helloworld.wrapper</extraarg>
<extraarg>-b</extraarg>
<extraarg>${basedir}/src/main/resources/bindings.xml</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.cxf.xjc-utils</groupId>
<artifactId>cxf-xjc-runtime</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
</project>
view raw gistfile1.xml hosted with ❤ by GitHub
<definitions targetNamespace="http://com.pelssers.helloworld/"
name="HelloWorldService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://com.pelssers.helloworld/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wrapper="http://com.pelssers.helloworld/wrapper">
<types>
<xsd:schema>
<xsd:import namespace="http://com.pelssers.helloworld/wrapper"
schemaLocation="xsd/helloworld.xsd" />
</xsd:schema>
</types>
<message name="helloWorldFault">
<part name="fault" element="wrapper:error" />
</message>
<message name="helloWorldRequest">
<part name="parameters" element="wrapper:helloWorldRequest"/>
</message>
<message name="helloWorldResponse">
<part name="parameters" element="wrapper:helloWorldResponse"/>
</message>
<portType name="HelloWorldService">
<operation name="sayHi">
<input message="tns:helloWorldRequest" />
<output message="tns:helloWorldResponse" />
<fault name="helloWorldFault" message="tns:helloWorldFault" />
</operation>
</portType>
<binding name="HelloWorldServicePortBinding" type="tns:HelloWorldService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<operation name="sayHi">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="helloWorldFault">
<soap:fault name="helloWorldFault" use="literal" />
</fault>
</operation>
</binding>
<service name="HelloWorldService">
<port name="HelloWorldServicePort" binding="tns:HelloWorldServicePortBinding">
<soap:address location="http://localhost:7001/HelloWorldService" />
</port>
</service>
</definitions>
view raw gistfile1.xml hosted with ❤ by GitHub
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema xmlns:tns="http://com.pelssers.helloworld/wrapper"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
targetNamespace="http://com.pelssers.helloworld/wrapper">
<xs:element name="helloWorldRequest" type="tns:HelloWorldRequestType" />
<xs:element name="helloWorldResponse" type="tns:HelloWorldResponseType" />
<xs:element name="error" type="tns:errorType"/>
<xs:element name="unused" type="xs:string"/>
<xs:element name="Unused" type="xs:integer"/>
<xs:complexType name="HelloWorldRequestType">
<xs:sequence>
<xs:element name="firstName" type="xs:string"/>
<xs:element name="first_name" type="xs:string"/>
<xs:element name="lastName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="HelloWorldResponseType">
<xs:sequence>
<xs:element name="greeting" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="reasonType">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ReasonType">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="errorType">
<xs:sequence>
<xs:element name="errorCode" type="xs:string"/>
<xs:element name="detail" type="xs:string"/>
<xs:element name="reason" type="tns:reasonType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
view raw gistfile1.xml hosted with ❤ by GitHub
<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jaxb:globalBindings generateElementProperty="false">
<jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime" />
<jaxb:javaType name="java.util.Date" xmlType="xsd:date"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime" />
<jaxb:javaType name="java.util.Date" xmlType="xsd:time"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printTime" />
</jaxb:globalBindings>
</jaxb:bindings>
view raw gistfile1.xml hosted with ❤ by GitHub

Eclipse will complain with following message

[ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [32,3]: (Relevant to above error) another "ReasonType" is generated from here. [ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [32,3]: Two declarations cause a collision in the ObjectFactory class. [ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [26,3]: (Related to above error) This is the other declaration. [ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [9,3]: Two declarations cause a collision in the ObjectFactory class. [ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [10,3]: (Related to above error) This is the other declaration. [ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [15,7]: Two declarations cause a collision in the ObjectFactory class. [ERROR] file:/playground/objectfactory/src/main/resources/xsd/helloworld.xsd [14,7]: (Related to above error) This is the other declaration. A class/interface with the same name "com.pelssers.helloworld.wrapper.ReasonType" is already in use. Use a class customization to resolve this conflict.

Below a version that fixes all issues. Ps. Sometimes it might also be useful to add @underscoreBinding="asCharInWord" to the globalBindings.

<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jaxb:globalBindings generateElementProperty="false">
<jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime" />
<jaxb:javaType name="java.util.Date" xmlType="xsd:date"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime" />
<jaxb:javaType name="java.util.Date" xmlType="xsd:time"
parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseTime"
printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printTime" />
</jaxb:globalBindings>
<jaxb:bindings schemaLocation="xsd/helloworld.xsd">
<jaxb:bindings
node="//xsd:complexType[@name='HelloWorldRequestType']/xsd:sequence/xsd:element[@name='firstName']">
<jaxb:property name="firstName1" />
</jaxb:bindings>
<jaxb:bindings
node="//xsd:complexType[@name='HelloWorldRequestType']/xsd:sequence/xsd:element[@name='first_name']">
<jaxb:property name="firstName2" />
</jaxb:bindings>
<jaxb:bindings node="//xsd:complexType[@name='reasonType']">
<jaxb:class name="ReasonType1" />
</jaxb:bindings>
<jaxb:bindings node="//xsd:complexType[@name='ReasonType']">
<jaxb:class name="ReasonType2" />
</jaxb:bindings>
<jaxb:bindings node="xsd:element[@name='unused']">
<jaxb:factoryMethod name="String"/>
</jaxb:bindings>
<jaxb:bindings node="xsd:element[@name='Unused']">
<jaxb:factoryMethod name="Integer"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
view raw gistfile1.xml hosted with ❤ by GitHub

Tuesday, April 15, 2014

Javascript promises demo

/**
* Check out following URL's
* http://www.html5rocks.com/en/tutorials/es6/promises/
* http://www.html5rocks.com/en/tutorials/es6/promises/#toc-async
* http://blog.parse.com/2013/01/29/whats-so-great-about-javascript-promises/
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
*
* Try this code out on http://repl.it/
*
* At present, promises are not yet supported by all browsers and some javascript libraries
* offer this functionality already.
*
* Q seems to be a popular implementation but it's performance seems not that good
* https://github.com/kriskowal/q
*
* Bleubird seems like the most promising implementation in terms of performance
* https://github.com/petkaantonov/bluebird
*
* I hope to find some time soon to prepare a demo with bluebird.
***/
function factorial(n) {
return new Promise(function(resolve, reject) {
if (n < 0) {
reject(new Error("n has to be larger than 0!!"));
} else {
var result = 1;
do {
result *= n;
n--;
}
while (n > 1);
return resolve(result);
}
});
}
function onSucces(result) {
console.log("succesfully calculated " + result);
}
function onError(error) {
console.log(error.toString());
}
factorial(5).then(onSucces, onError);
//succesfully calculated 120
factorial(-3).then(onSucces, onError);
//Error: n has to be larger than 0!!
view raw gistfile1.js hosted with ❤ by GitHub

Little Ajax exercise

Robby Pelssers 37
Valerie Pelssers 7
Lindsey Pelssers 11
view raw gistfile1.txt hosted with ❤ by GitHub
<!DOCTYPE html>
<html>
<head>
<title>Ajax demo</title>
<script data-main="scripts/ajax" src="scripts/require.js"></script>
</head>
<body>
<h1>This is a demo showing making an AJAX call<h1>
<div id="result"/>
</body>
</html>
view raw gistfile1.html hosted with ❤ by GitHub
require.config({
baseUrl: 'scripts',
paths: {
jquery: 'jquery-2.1.0.min'
}
});
requirejs(["jquery"], function($) {
/**
0 -> UNSENT
1 -> OPENED
2 -> HEADERS_RECEIVED
3 -> LOADING
4 -> DONE
**/
function handleStateChange() {
var readyState = request.readyState;
console.log(readyState);
switch(readyState) {
case 4:
processResponse(request.responseText);
break;
default:
break;
}
}
function nonEmptyString(value) {
return value !== "";
}
function processResponse(responseText) {
console.log("Processing responseText");
var lines = responseText.split('\n');
lines.filter(nonEmptyString).forEach(function(line) {
console.log("Processing line: " + line);
/**
* TODO: dynamically build a table for each line from the CSV file with JQuery
* appended as child within <div id="result"/>
**/
});
}
console.log("About to make Ajax request");
var request = new XMLHttpRequest();
request.open("GET", "data/persons.csv", true);
request.onreadystatechange = handleStateChange;
request.send();
console.log("Ajax request has been sent");
});
view raw gistfile1.js hosted with ❤ by GitHub

Javascript XPath Demo

<!DOCTYPE html>
<html>
<head>
<title>Xpath demo</title>
<script data-main="scripts/xpath" src="scripts/require.js"></script>
</head>
<body>
<h1>This is a demo showing querying the dom via Xpath<h1>
<ul>
<li>Javascript</li>
<li>Java</li>
<li>Scala</li>
<li>Ceylon</li>
<li>Python</li>
</ul>
</body>
</html>
view raw gistfile1.html hosted with ❤ by GitHub
/**
https://developer.mozilla.org/en-US/docs/Web/XPath
**/
requirejs([], function() {
//count the number of <li> tags
var listItemCount = document.evaluate( 'count(/html/body//li)', document, null, XPathResult.ANY_TYPE, null );
alert("There are " + listItemCount.numberValue + " <li> tags inside the <body> tag");
//output: There are 5 <li> tags inside the <body> tag
//stringjoin the values of the <li> nodes
var iterator = document.evaluate('/html/body//li', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
var listItem;
var listItemValues = [];
while (listItem = iterator.iterateNext()) {
listItemValues.push(listItem.textContent);
}
alert("The languages listed are '" + listItemValues.join() + "'.");
//output: The languages listed are 'Javascript,Java,Scala,Ceylon,Python'.
});
view raw gistfile1.js hosted with ❤ by GitHub

Saturday, April 12, 2014

AngularJS demo

/**
* movies.json
**/
[
{
"title": "Avatar",
"year": 2009,
"director": "James Cameron",
"actors": ["Sam Worthington", "Sigourney Weaver"]
},
{
"title": "Aliens",
"year": 1986,
"director": "James Cameron",
"actors": ["Michael Biehn", "Sigourney Weaver"]
},
{
"title": "The Terminator",
"year": 1984,
"director": "James Cameron",
"actors": ["Michael Biehn", "Arnold Schwarzenegger", "Linda Hamilton"]
},
{
"title": "Indiana Jones and the Temple of Doom",
"year": 1984,
"director": "Steven Spielberg",
"actors": ["Harrison Ford", "Kate Capshaw"]
}
]
view raw gistfile1.js hosted with ❤ by GitHub
<!DOCTYPE html>
<html ng-app="moviesApp">
<!-- This demo only works in you serve the files from tomcat or any other webserver -->
<head>
<title>AngularJS demo</title>
<link rel="stylesheet" href="styles/movies.css" type="text/css"/>
<script data-main="scripts/movies" src="scripts/require.js"></script>
</head>
<body ng-controller="moviesController">
<h1>This page is dynamically constructed using AngularJS</h1>
<p>Total number of movies is {{movies.length}}</p>
<div>Search: <input ng-model="query"></div>
<div>Sort by:
<select ng-model="orderProp">
<option value="director">director</option>
<option value="title">title</option>
<option value="year">year</option>
</select>
</div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Year</th>
<th>Director</th>
<th>Actors</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="movie in movies | filter:query | orderBy:orderProp">
<td>{{movie.title}}</td>
<td>{{movie.year}}</td>
<td>{{movie.director}}</td>
<td>{{movie.actors.join(",")}}</td>
</tr>
<tbody>
</body>
</html>
view raw gistfile1.html hosted with ❤ by GitHub
/* movies.css */
table {
border-collapse:collapse;
}
th {
text-align: left;
padding:3px;
border: 1px solid red;
}
td {
border: 1px dotted black;
padding: 3px;
}
view raw gistfile1.css hosted with ❤ by GitHub
/**
* movies.js
**/
require.config({
baseUrl: 'scripts',
paths: {
'angular': 'angular.min'
},
shim: {
"angular": {
exports: "angular"
}
}
});
requirejs(['angular'], function(angular) {
var moviesApp = angular.module('moviesApp', []);
moviesApp.controller('moviesController', function ($scope, $http) {
$http.get('data/movies.json')
.success(function(data) {
$scope.movies = data;
});
$scope.orderProp = 'title';
});
});
view raw gistfile1.js hosted with ❤ by GitHub

HTML5 Web Workers demo

<!DOCTYPE html>
<html>
<!-- This demo only works in you serve the files from tomcat or any other webserver -->
<head>
<title>Webworker demo</title>
<script data-main="scripts/app" src="scripts/require.js"></script>
</head>
<body>
<div><button id="mean">get mean</button></div>
<div><button id="max">get max</button></div>
</body>
</html>
view raw gistfile1.html hosted with ❤ by GitHub
/** data.js
// data generated using http://repl.it/languages/JavaScript
var numbers = [];
for (var i =0; i < 1000; i++) {
numbers.push(Math.round(Math.random() * 1000));
}
console.log(JSON.stringify(numbers));
**/
define({
"numbers": [375,797,951,183,732,780,599,597,156,446,156,100,58,459,866,334,601,143,708,651,21,56,970,722,832,939,212,1,182,992,183,617,304,612,525,7,432,23,291,525,612,400,139,47,292,974,366,233,456,91,785,618,200,382,514,983,592,467,46,860,608,680,171,450,65,13,949,942,966,563,808,385,305,16,98,231,684,241,440,683,122,610,495,833,34,173,909,391,259,182,663,755,312,425,520,208,547,568,185,31,970,842,775,450,939,395,895,927,598,727,922,327,88,570,196,521,45,961,325,845,389,747,271,540,829,587,357,965,281,607,543,276,141,296,802,165,75,16,987,423,772,395,199,293,6,14,815,199,707,711,729,790,771,606,74,926,358,651,116,915,863,850,623,449,331,95,64,371,311,669,325,666,730,591,638,275,887,561,472,383,120,972,713,849,761,722,561,236,771,256,494,40,523,711,428,111,25,439,108,202,31,896,636,475,314,563,509,696,908,139,249,604,410,540,756,203,229,943,77,599,290,695,161,880,930,624,808,296,633,105,871,457,804,218,187,417,893,883,539,324,807,122,896,356,318,907,110,272,228,648,427,1,818,353,861,305,7,165,511,534,417,485,222,692,120,269,338,244,943,168,323,219,519,558,703,404,364,65,972,254,962,247,252,696,497,712,301,148,285,998,37,267,610,977,503,411,51,33,279,345,908,634,240,681,145,531,489,448,986,553,242,593,672,81,762,370,238,242,728,803,368,470,632,983,634,399,536,816,90,798,835,151,321,508,187,696,41,858,591,326,678,220,17,711,512,810,226,349,645,96,174,941,691,398,387,518,937,838,138,676,341,735,113,209,925,541,877,696,258,229,660,175,817,982,555,517,530,261,242,996,93,965,897,558,900,883,633,189,339,279,349,700,726,847,897,856,887,405,780,888,642,851,84,936,162,785,899,669,606,581,9,372,101,940,664,974,5,284,161,305,549,486,692,448,652,994,224,176,712,18,237,494,325,179,746,366,650,744,849,721,658,308,568,543,94,509,368,636,265,250,244,590,973,979,393,487,892,906,631,434,795,350,503,645,577,669,493,864,195,230,722,499,281,572,24,769,645,44,177,995,940,470,954,280,915,883,370,748,15,953,928,331,428,553,967,572,964,980,853,75,294,306,385,191,851,268,317,485,169,373,557,395,936,844,696,930,570,70,97,209,615,671,990,359,140,254,518,295,877,323,741,849,697,137,702,709,359,553,294,297,809,420,810,256,867,612,913,82,511,5,502,628,798,194,650,71,702,397,796,51,890,887,338,28,376,579,94,438,578,672,36,328,466,155,543,982,287,839,591,860,31,250,37,39,823,303,360,537,127,327,522,828,770,272,216,965,623,457,85,842,52,194,531,411,541,700,637,138,726,133,976,970,516,715,323,41,795,399,271,434,439,744,78,251,25,184,963,81,836,428,696,688,409,58,173,915,156,442,250,240,549,94,715,183,660,935,280,638,955,517,738,657,554,436,612,730,420,48,248,566,356,159,758,120,14,342,116,92,46,94,41,311,855,980,704,175,474,17,98,763,492,807,473,346,173,465,434,650,399,48,616,949,635,887,45,261,375,15,626,933,503,501,856,539,659,684,163,616,71,944,642,944,27,867,586,636,940,801,575,677,388,573,643,129,458,811,546,821,941,626,386,820,961,651,905,207,196,274,69,215,101,377,18,39,94,618,683,337,71,656,319,385,845,682,23,341,814,261,282,496,118,693,697,348,629,937,877,39,735,418,803,968,282,548,177,423,751,569,807,576,991,732,413,128,372,250,776,581,341,867,931,562,858,239,429,680,751,740,755,238,103,378,903,534,505,497,826,390,320,298,896,100,389,53,11,959,905,847,91,355,319,957,950,677,951,483,573,493,632,83,448,92,293,602,329,554,673,213,752,946,792,781,790,113,91,931,494,974,58,996,550,56,442,737,888,546,351,706,117,969,143,688,762,837,618,867,101,838,84,426,701,223,73,397,822,892,706,147,81,513,85,233,987,581,374,863,371,880,813,237,947,908,986,592,753,350,376,708,84,482,777,378,558,705,424,249,906,330,111,434,493,254,11,405,469,571,56,741,119,767,118,823,649,744,746,681,583,238,962,400,375,478,286,83,869,528,224,436,963,802,12,978,970,556,43,323,891,43,528,925,993,919,74,253,554,695,969,75,523,166,629,217,696,294,455,996,628,697,584,384,901,737,45,915,281,959,950,58,890,395,456,107,620,336,277,170,188,647,464,388,353,229,584,266,78,360,974,260,986,453]
});
view raw gistfile1.js hosted with ❤ by GitHub
/** mathworker.js **/
function max(numbers) {
return Math.max.apply(Math, numbers);
}
function mean(numbers) {
var sum = numbers.reduce(function(acc, num){ return acc + num; }, 0);
return sum / numbers.length;
}
onmessage = function(event) {
var message = event.data;
var command = message.command;
var numbers = message.numbers;
switch (command) {
case "max":
postMessage("The max number is " + max(numbers));
break;
case "mean":
postMessage("The mean of these numbers is " + mean(numbers));
break;
default:
postMessage("Unknown command issued!!");
break;
}
}
view raw gistfile1.js hosted with ❤ by GitHub
require.config({
baseUrl: 'scripts',
paths: {
// the left side is the module ID,
// the right side is the path to
// the jQuery file, relative to baseUrl.
// Also, the path should NOT include
// the '.js' file extension. This example
// is using jQuery 2.1.0 located at
// scripts/jquery-2.1.0.min.js, relative to
// the HTML page.
jquery: 'jquery-2.1.0.min'
}
});
requirejs(["jquery","./data"], function($, staticdata) {
function createMathWorker() {
var worker = new Worker("scripts/mathworker.js");
worker.onmessage = function(e) {
alert(e.data);
}
return worker;
}
function getValue(event) {
var numbers = staticdata.numbers;
var command = event.data.command;
console.log("dispatching calculating " + command + " to worker");
var message = { "command": command, "numbers": numbers};
worker.postMessage(message);
}
var worker = createMathWorker();
$("#max").on("click", {"command": "max"}, getValue);
$("#mean").on("click", {"command": "mean"}, getValue);
});
view raw gistfile1.js hosted with ❤ by GitHub

Friday, April 11, 2014

Javascript event delegation (bubbling)

<!DOCTYPE html>
<html>
<head>
<title>Using event delegation</title>
<script src="scripts/matchers.js"></script>
<script src="scripts/eventdelegation.js"></script>
</head>
<body>
<div id="item-list">
<div class="item">Item 1</div>
<span class="item">Item 2</span>
<h3>Item 3</h3>
</div>
</body>
</html>
view raw gistfile1.html hosted with ❤ by GitHub
/**
* matchers.js
**/
/***********************************************************/
function Matchers(matchers) {
this.matchers = matchers || [];
}
Matchers.prototype.getMatchers = function() {
return this.matchers;
}
Matchers.prototype.add = function(matcher) {
return new Matchers(this.matchers.concat(matcher));
}
Matchers.prototype.matches = function(obj) {
return this.matchers.every(function(matcher){
return matcher.matches(obj);
});
}
Matchers.from = function() {
var matchers = [];
for (var i=0, len=arguments.length; i < len; i++) {
matchers.push(arguments[i]);
}
return new Matchers(matchers);
}
/***********************************************************/
function AbstractMatcher(predicate) {
this.predicate = predicate;
}
AbstractMatcher.prototype.matches = function(obj) {
return this.predicate(obj);
}
/***********************************************************/
ElementMatcher.prototype.constructor = ElementMatcher;
ElementMatcher.prototype = new AbstractMatcher();
function ElementMatcher(predicate) {
AbstractMatcher.prototype.constructor.call(this, predicate);
}
ElementMatcher.byClassName = function(className) {
return new ElementMatcher(
function(element) {
var classes = element.className.split(" ");
if (!classes) return false;
return classes.indexOf(className) > -1;
}
);
}
ElementMatcher.byNodeName = function(nodeName) {
return new ElementMatcher(
function(element) {
return element.nodeName === nodeName.toUpperCase();
}
);
}
/***********************************************************/
view raw gistfile1.js hosted with ❤ by GitHub
/**
* eventdelegation.js
*
* Remark: this does not work in IE as I use addEventListener which is not supported by IE.
**/
window.onload = (function(){
return function(){
//only place an onclick handler on the parent and let onclick events from the actual
//items bubble up to the parent where we handle them
document.getElementById("item-list").addEventListener("click", function(event) {
var target = event.target;
if (Matchers.from(ElementMatcher.byNodeName("div"), ElementMatcher.byClassName("item")).matches(target)) {
alert("You clicked on a <div class=\"item\"> with value '" + target.innerHTML + "'");
} else if(ElementMatcher.byClassName("item").matches(target)) {
alert("You clicked on a element with class=\"*item*\" with value '" + target.innerHTML + "'");
} else {
alert("We are not handling this click event");
}
});
};
})();
/** Compare this to JQuery
http://api.jquery.com/on/
//attach an onlick handler to each table row
$( "#dataTable tbody tr" ).on( "click", function() {
alert( $( this ).text() );
});
//attach an onclick handler to the table rows container -> tbody (use event delegation)
$( "#dataTable tbody" ).on( "click", "tr", function() {
alert( $( this ).text() );
});
**/
view raw gistfile1.js hosted with ❤ by GitHub