We use the Bind () method primarily to call a function with the this value set explicitly. It occurs when we use the this keyword when a function or method is invoked.
Bind appear in ECMAScript5, so for older systems you can add this code:
if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeofthis !== 'function') { // closest thing possible to the ECMAScript 5 internal IsCallable function thrownewTypeError ('Function.prototype.bind' + ' - what is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call (arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { return fToBind.apply (thisinstanceof fNOP && oThis ? this : oThis, aArgs.concat (Array.prototype.slice.call (arguments))); };
Let’s use an example: when we click the button we populate the text field randomly
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var user = { data: [ {name: 'T. Woods', age: 37}, {name: 'P. Mickelson', age: 43} ], clickHandler:function (event) { // random number between 0 and 1 var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // This line is adding a random person from the data array to the text field $ ('input').val (this.data[randomNum].name + " " + this.data[randomNum].age); } } // Assign an eventHandler to the button's click event $ ('button').click (user.clickHandler);
If we use a framework like JQuery or Backbone.js it will work as it will do most of the binding process for us, but if not this will fail as the method is bound to the HTML element (it is where the method is executed on).
// This data variable is a global variable var data = [ {name: 'Sam', age: 12}, {name: 'Alex', age: 14} ]; var user = { // local data variable data: [ {name: 'T. Woods', age: 37}, {name: 'P. Mickelson', age: 43} ], showData: function (event) { // random number between 0 and 1 var randomNum = ((Math.random () * 2 | 0) + 1) - 1; console.log (this.data[randomNum].name + ' ' + this.data[randomNum].age); } }
// Assign the showData method of the user object to a variable var showDataVar = user.showData; showDataVar (); // Sam 12 (from the global data array, not from the local data array)
// FIX: Bind the showData method to the user object var showDataVar = user.showData.bind (user); // Now we get the value from the user object, // because the 'this' keyword is bound to the user object showDataVar (); // P. Mickelson 43
“Apply” and “Call”
Allow us to borrow functions and set the value this in function invocation.
// global variable for demonstration var avgScore = 'global avgScore';
//global function functionavg (arrayOfScores) { // Add all the scores and return the total var sumOfScores = arrayOfScores.reduce (function (prev, cur, index, array) { return prev + cur; });
// The 'this' keyword here will be bound to the global object, // unless we set the 'this' with Call or Apply this.avgScore = sumOfScores / arrayOfScores.length; }
var gameController = { scores: [20, 34, 55, 46, 77], avgScore: null } // If we execute the avg function, 'this' inside // the function is bound to the global window object: avg (gameController.scores); // Proof that the avgScore was set on the global window object console.log (window.avgScore); // 46.4 console.log (gameController.avgScore); // null // reset the global avgScore avgScore = 'global avgScore'; // To set the "this" value explicitly, so that 'this' is bound to the gameController, // We use the call () method: avg.call (gameController, gameController.scores); console.log (window.avgScore); //global avgScore console.log (gameController.avgScore); // 46.4
grunt concat //executes a multitask grunt concat:foo //executes the foo sutask, which is part of concat
Tasks can call asynchronous functions.
1 2 3 4 5
grunt.registerTask('asyncme', "My asynchronous task", function(){ // done will be executed once the task is finished var done = this.async(); doSomethingAsync(done); }
Mapping files
Parameters:
src: source path
dest: destination path
filter: file system native functions, to filter the files to load (e.g. supports the ** from the relative paths)
nonull: if true, it will include files which wont pass the filter
dot: add files whose name starts with the chracter ‘.’
matchbase: if it’s defined, the files will be searched starting on this dir
expand: processes a dynamically the src & dest mapping
grunt.registerTask('install', [], installTaks); grunt.registerMultiTask('packgrInstall', 'Download all the assets from dependencies', function(){installTask(grunt, this); });
One of the challenges I had to face a couple of years ago was to migrate a Java desktop application from 32 bits to 64 bits architecture, and what may have been as simple as using the right JDK, switching to the proper external libraries versions and getting rid of the deprecated code actually had an extra issue. The application embeded a 32 bits PDF reader on a panel, and that limitation had been stopping this migration for a while.
One of the challenges I had to face a couple of years ago was to migrate a Java desktop application from 32 bits to 64 bits architecture, and what may have been as simple as using the right JDK, switching to the proper external libraries versions and getting rid of the deprecated code actually had an extra issue. The application embeded a 32 bits PDF reader on a panel, and that limitation had been stopping this migration for a while.
Going into the code itself, it was using the XULRunner, one of the Firefox engine components, so what it actually did was “using a 32 bits Firefox browser embedded”. It also used Adobe Acrobat generated interactive forms, which actually required Adobe Acrobat Reader itself to be rendered properly and this took Apache PDFBox out of the picture to do this task.
When I looked into the philosophy of running an embed browser I tried to take what happened in my laptop: when I was surfing the net and opening a PDF file my Firefox 32 bits browser, I didn’t use some browser code: I delegated this in the Adobe Acrobat Reader X Plugin for the browser. So, why should not we take this idea one step further, and use the same plugin through an integration? Adobe itself provides this system, so there would be no incompatibility issue, I just had to setup this through the operating system configuration to get a workaround and get the proper version for the machine architecture in which we are currently running the program.
So let’s meet DJNativeSwing, a library based in SWT (Standard Widget Toolkit) which allows us to have our very own embedded browser in our code. SWT is highly recommended library due to its portability, as it accesses to the Native Operating System GUIs, and that is exactly what we require for this kind of issue. It is also the next wrapping level to Java Swing, and actually lighter and faster, and I had already used it back in the day to avoid problems when I had to deal with Macromedia Flash plugin integrations.
As an example of how to configure this, we are going to follow 2 basic steps:
Set up a browser tab on a Java swing component.
Be able to open a PDF on that said browser tab.
Process
1. Previous set up: the Maven dependecies required
Let’s start with the basics: first of all we will get the maven dependencies.
❕This was the stable version when the post was originally written.
Right after that, we will define the basic window frame, with a button the select the file (via FileChooser) and a panel to show the results.
❕Setting up all the text strings as constants makes them easier to spot them in order to replace them if needed. It’s not really necessary, but doing it improves reusability.
publicclassDemoPDFRenderLauncher { privatestaticfinalStringTITLE="PDF Renderer demo"; privatestaticfinalStringNO_OUTPUT_MESSAGE="No output available"; privatestaticfinalStringNO_DATA_MESSAGE="There is no data available from form"; privatestaticfinalintLENGTH=800; privatestaticfinalintWIDTH=600; privatestaticfinal String FILTER_FILES "PDF files"; privatestaticfinal String FILE_EXTENSION "pdf";
/** * The main app window */ private JFrame window; /** * The path of the file we will open */ private String path; /** * Button for open file function */ private JButton buttonOpen; /** * A browser panel */ private BrowserPanel browserPanel;
/** * Initializes the browser and sets a value in the URL storage * @param path the URL value o file path to open */ publicvoidnavigate(String path) { webBrowser.setVisible(true); webBrowser.navigate(path); } /** * Makes the browser retrieve and render the content from the path previously stored */ public String getAddress(){ return webBrowser.getHTMLContent(); } /** * Hides the browser controls (forward, back, home buttons...) */ publicvoidhideContent() { webBrowser.setVisible(false); } }
This way we are getting a fully functional web browser, very similar to the browser in the Eclipse IDE, but with too many unnecessary functions for what we are trying to do here. Since we are only doing the rendering process by delegating it on Adobe, we can remove the GUI extra elements from this whole custom browsing system and leave the bare panel.
/** * Allows to launch a JFrame containing an embedded browser. */ publicclassBrowserFrameLauncher {
/** * Renders the file content on a browser via DJ Native Swing * * @param path * the file url if we pass as a parameter any webpage URL, * the system would try to render it * @return a JPanel with a native browser, to render the file content */ private Component createBrowserPanel(String path) { JWebBrowser.useXULRunnerRuntime(); JPanelfileBrowserPanel=newJPanel(newBorderLayout()); finalJWebBrowserfileBrowser=newJWebBrowser(); fileBrowser.setBarsVisible(false); fileBrowser.setStatusBarVisible(false); fileBrowser.navigate(path); fileBrowserPanel.add(fileBrowser, BorderLayout.CENTER); return fileBrowserPanel; }
}
4. Setting the last piece of the puzzle: getting the PDF itself
Finally let’s make the final touches to open a PDF. What we are actually doing is getting the PDF file path into the browser, so in the end we have a new layer over our old friend XULRunner, but this provides us a way to integrate the plugins via the “right architecture version” SWT library. So as a conclussion we are able to connect to the “right architecture version” plugin, fixing our rendering problem and making us independent from the 32 bits plaform once and for all.
privatestaticfinalStringCLOSING_MESSAGE="Do you really want to close the file?"; privatestaticfinalStringRENDERED_TITLE="PDF Renderer demo - Embed Browser";
/** * Opens a file and shows it content in a JFrame. * * @param path * the url of the file to open in a JFrame */ publicstaticvoidopenPDF(final String path) { NativeInterface.open(); SwingUtilities.invokeLater(newRunnable() { publicvoidrun() { finalJFrameframe=newJFrame(RENDERED_TITLE); frame.setLocation(0, 0); //we may set up a default size for this test //frame.setSize(800, 600); frame.setVisible(true); frame.add(createBrowserPanel(path)); //a window listener would allow us to control the closing actions frame.addWindowListener(newWindowAdapter() { publicvoidwindowClosing(WindowEvent e) { inti= JOptionPane.showConfirmDialog(frame,CLOSING_MESSAGE); if (i == 0) { NativeInterface.close(); } } }); } }); }
❗️ Please notice the NativeInterface.open() line to make sure about getting the components correctly booted, and the threading of this component in order to avoid other processes interfering with the rendering.
// don't use Jquery until the page is loaded $(document).ready(function(){ // jQuery $(selector).action(); }); $(function(){ // more jQuery after load $(selector).action(); });
$ access to jQuery.
(selector) gets HTML element
action() does operation on element
Selectors
by name, id, class, type, attributes, value…
1 2 3 4 5 6 7
$(document).ready(function(){ // when click on button $(' button').click(function(){ // hide paragraph $('p' ).hide(); }); });
$("#button") -> id="button" -> ids should be unique
$(".button") -> class="button" -> may return many
Callbacks on Jquery
With callback
1 2 3 4 5 6 7 8 9 10
$(document).ready(function(){ $('button').click(function(){ $('p').hide('slow', function() { // once hidden, show alert alert('The paragraph is now hidden'); }); }); }); //executed first alert("The paragraph is not hidden");
Without callback
1 2 3 4 5
$('button').click(function(){ $('p').hide(1000); // it will not wait for the paragraphs to be hidden alert('The paragraph is now hidden'); });
Chaining
1 2 3 4
// animation: silde up and down $('#p1').css('color', 'red') .slideUp(2000) .slideDown(2000);
Working with the DOM
No parameters = “gets”. With parameters = “sets”
text(): no format, text.
html(): with format, HTML
val(): value field
atr('atrib', 'new value'): set, similar to val('')
allow asynchronous communication bertween server and browser in XML via JS
loads data in background and deploys them without a full web reload
jQuery uses HTTP GET y POST to obtain text, HTML, XML or JSON de un servidor remoto
3 functions with similar parameters:
load
1 2 3 4
$(selector).load(url, data, callback); // url: mandatory // data: <key,value> pairs for the request, optional // callback: whet should it do after `load()`, optional
RequireJS is the async loader we have been talking about in the AMD section.
NodeJs adds a loader which uses the CommonJS formatS, which doesn’t deal well with the browser.
Using RequireJS allows us using a single format for all the modules, server or client.
It can be configured for only client use.
The NodeJs adapter (r.js) for RequireJS will use the require implementation and search for paths in NodeJS if the module can’t be found its configuration: RequireJS will assume it is a module which uses config and modules type NodeJS.
Configuration
First we add the library to our project:
1 2
<scriptdata-main="/pages/<%= distName %>/<%= version %>/js/config" src="/pages/<%= distName %>/<%= version %>/js/vendor/require.js"></script>
By loading RequireJS, we get access to the “require” object. The data-main loads the input point for every dependency on our app (in this case it would be “config.js”, which also configures the “require” object). From here on, we should follow AMD patterns on our modules. Example:
1 2 3
require(["jquery"], function($) { $("#mydiv").html("Hello this is RequireJS talking"); });