Dec 14 2018
Dec 14

A lot of people have been jumping on the headless CMS bandwagon over the past few years, but I’ve never been entirely convinced. Maybe it’s partly because I don’t want to give up on the sunk costs of what I’ve learned about Drupal theming, and partly because I’m proud to be a boring developer, but I haven’t been fully sold on the benefits of decoupling.

On our current project, we’ve continued to take an approach that Dries Buytaert has described as “progressively decoupled Drupal”. Drupal handles routing, navigation, access control, and page rendering, while rich interactive functionality is provided by a JavaScript application sitting on top of the Drupal page. In the past, we’d taken a similar approach, with AngularJS applications on top of Drupal 6 or 7, getting their configuration from Drupal.settings, and for this project we decided to use React on top of Drupal 8.

There are a lot of advantages to this approach, in my view. There are several discrete interactive applications on the site, but the bulk of the site is static content, so it definitely makes sense for that content to be rendered by the server rather than constructed in the browser. This brings a lot of value in terms of accessibility, search engine optimisation, and performance.

A decoupled system is almost inevitably more complex, with more potential points of failure.

The application can be developed independently of the CMS, so specialist JavaScript developers can work without needing to worry about having a local Drupal build process.

If at some later date, the client decides to move away from Drupal, or at the point where we upgrade to Drupal 9, the applications aren’t so tightly coupled, so the effort of moving them should be smaller.

Having made the decision to use this architecture, we wanted a consistent framework for managing application configuration, to make sure we wouldn’t need to keep reinventing the wheel for every application, and to keep things easy for the content team to manage.

The client’s content team want to be able to control all of the text within the application (across multiple languages), and be able to preview changes before putting them live.

There didn’t seem to be an established approach for this, so we’ve built a module for it.

As we’ve previously mentioned, the team at Capgemini are strongly committed to supporting the open source communities whose work we depend on, and we try to contribute back whenever we can, whether that’s patches to fix bugs and add new features, or creating new modules to fill gaps where nothing appropriate already exists. For instance, a recent client requirement to promote their native applications led us to build the App Banners module.

Aiming to make our modules open source wherever possible helps us to think in systems, considering the specific requirements of this client as an example of a range of other potential use cases. This helps to future-proof our code, because it’s more likely that evolving requirements can be met by a configuration change, rather than needing a code change.

So, guided by these principles, I’m very pleased to announce the Single Page Application Landing Page module for Drupal 8, or to use the terrible acronym that it has unfortunately but inevitably acquired, SPALP.

On its own, the module doesn’t do much other than provide an App Landing Page content type. Each application needs its own module to declare a dependency on SPALP, define a library, and include its configuration as JSON (with associated schema). When a module which does that is installed, SPALP takes care of creating a landing page node for it, and importing the initial configuration onto the node. When that node is viewed, SPALP adds the library, and a link to an endpoint serving the JSON configuration.

Deciding how to store the app configuration and make all the text editable was one of the main questions, and we ended up answering it in a slightly “un-Drupally” way.

On our old Drupal 6 projects, the text was stored in a separate ‘Messages’ node type. This was a bit unwieldy, and it was always quite tricky to figure out what was the right node to edit.

For our Drupal 7 projects, we used the translation interface, even on a monolingual site, where we translated from English to British English. It seemed like a great idea to the development team, but the content editors always found it unintuitive, struggling to find the right string to edit, especially for common strings like button labels. It also didn’t allow the content team to preview changes to the app text.

We wanted to maintain everything related to the application in one place, in order to keep things simpler for developers and content editors. This, along with the need to manage revisions of the app configuration, led us down the route of using a single node to manage each application.

This approach makes it easy to integrate the applications with any of the good stuff that Drupal provides, whether that’s managing meta tags, translation, revisions, or something else that we haven’t thought of.

The SPALP module also provides event dispatchers to allow configuration to be altered. For instance, we set different API endpoints in test environments.

Another nice feature is that in the node edit form, the JSON object is converted into a usable set of form fields using the JSON forms library. This generic approach means that we don’t need to spend time copying boilerplate Form API code to build configuration forms when we build a new application - instead the developers working on the JavaScript code write their configuration as JSON in a way that makes sense for their application, and generate a schema from that. When new configuration items need to be added, we only need to update the JSON and the schema.

Each application only needs a very simple Drupal module to define its library, so we’re able to build the React code independently, and bring it into Drupal as a Composer dependency.

The repository includes a small example module to show how to implement these patterns, and hopefully other teams will be able to use it on other projects.

As with any project, it’s not complete. So far we’ve only built one application following this approach, and it seems to be working pretty well. Among the items in the issue queue is better integration with configuration management system, so that we can make it clear if a setting has been overridden for the current environment.

I hope that this module will be useful for other teams - if you’re building JavaScript applications that work with Drupal, please try it out, and if you use it on your project, I’d love to hear about it. Also, if you spot any problems, or have any ideas for improvements, please get in touch via the issue queue.

May 08 2018
May 08
May 8th, 2018

Over the past few months, Four Kitchens has worked together with the Public Radio International (PRI) team to build a robust API in PRI’s Drupal 7 site, and a modern, fresh frontend that consumes that API. This project’s goal was to launch a new homepage in the new frontend. PRI intends to re-build their entire frontend in this new structure and Four Kitchens has laid the groundwork for this endeavor. The site went live successfully, with a noticeable improvement in load time and performance. Overall load time performance increased by 40% with first-byte time down to less than 0.5 seconds. The results of the PRI team’s efforts can be viewed at PRI.org.

PRI is a global non-profit media company focused on the intersection of journalism and engagement to effect positive change in people’s lives. PRI’s mission is to serve audiences as a distinctive content source for information, insights and cultural experiences essential to living in our diverse, interconnected world.

Overall load time performance increased by 40% with first-byte time down to less than 0.5 seconds.

Four Kitchens and PRI approached this project with two technical goals. The first was to design and build a full-featured REST API in PRI’s existing Drupal 7 application. We used RESTFul, a Drupal module for building APIs, to create a JSON-API compliant API.

Our second technical goal was to create a robust frontend backed by the new API. To achieve that goal, we used React to create component-based user interfaces and styled them with using the CSS Modules pattern. This work was done in a library of components in which we used Storybook to demonstrate and test the components. We then pulled these components into a Next-based application, which communicates with the API, parses incoming data, and uses that data to populate component properties and generate full pages. Both the component library and the Next-based application used Jest and Enzyme heavily to create thorough, robust tests.

A round of well-deserved kudos to the PRI team: Technical Project Manager, Suzie Nieman managed this project from start to finish, facilitating estimations that led the team to success. Senior JavaScript Engineer, Patrick Coffey, provided keen technical leadership as well as deep architectural knowledge to all facets of the project, keeping the team unblocked and motivated. Engineer, James Todd brought his Drupal and JavaScript expertise to the table, architecting and building major portions of PRI’s new API. Senior Frontend Engineer, Evan Willhite, brought his wealth of frontend knowledge to build a robust collection of elegant components in React and JavaScript. Architect, David Diers created mechanisms that will be responsible for managing PRI’s API documentation that can be used in future projects.

Special thanks to Patrick Coffey and Suzie Nieman for their contributions to this launch announcement. 

Four Kitchens

The place to read all about Four Kitchens news, announcements, sports, and weather.

Mar 01 2018
Mar 01

A great developer experience or a great user experience? A familiar web technology for you to code in or native-like performance for your users? And these are just some of the questions “taunting” you right now, while dealing with a PhoneGap vs React Native dilemma, right?

Each platform comes with its own “temptations” to... lure you in:
 

  • PhoneGap promises you an “easy life” as a mobile app developer, enabling you to use any JavaScript library and framework that you're comfortable working with
  • React Native promises you to inject native-like performance into your app and thus...  to perfect the user experience
     

So, which one to go with?
 

PhoneGap: A Brief Overview

A compromise! This is, in my opinion, the perfect word/metaphor to describe PhoneGap.

A compromise in terms of user experience and performance, since it's hybrid mobile apps that you get to build using this technology:
 

  • a JS/CSS/HTML app having a browser-based UI (giving you the freedom to work in any of your preferred web technologies)
  • that exposes native mobile device APIs and data; accessing phone components through the API navigator
     

While a more “formal” definition would go something like this:

PhoneGap is a distribution of Apache Cordova — coming with a few tweaks and custom packages —  that you can use for embedding websites in mobile apps via WebView.

In short: more than a website, yet not a fully native mobile app. A hybrid app compromise!
 

A Few Words About React Native 

In a  PhoneGap vs React Native debate, the latter would always have its native components rendering “trump card” up its sleeve:

For a React Native-powered app is written in JS, like a PhoneGap one, yet it doesn't just render a webview, but REAL native components instead!

And that, my friend, would also win over users: it's better user experience and zero compromises on performance that you get “rewarded” with for using React Native.

You could also take this mobile app development platform as the answer to users' becoming more and more demanding:

If hybrid, HTML 5 and/or mobile web apps used to be enough to “satisfy” their needs, while being a “blessing” for developers' budgets, as well, mobile users started to crave native-like performance. And so, React Native emerged!

It's a convenient “bridge” between JS and native platforms:
 

  • React Native apps get written in JavaScript
  • they “play by the rules” and meet the standards of the operating system
  • ... while accessing a big part of the native platforms via this metaphoric “bridge” that React Native creates
     

PhoneGap: Tempting Benefits vs Discouraging Disadvantages

Now in order to get an accurate score to our “PhoneGap vs React Native” debate here, we'd better go “pros and cons harvesting”, right?

So, without any further ado, I'll list some of PhoneGap's “irresistible” advantages first:
 

  • it “spoils” the developer with a wide range of frameworks/libraries to choose from; if you're a big fan of web technologies, if you enjoy building UIs in HTML and CSS, you'll love the rich collection of choices that PhoneGaps puts at your disposal
  • therefore, PhoneGap is easy to work with and developer-friendly
  • it's not bound to any specific framework 
  • PhoneGap-based apps perform within wrappers targeted to each platform and use API bindings that comply with the all the given standards for accessing each mobile device's data, network status, sensors
  • it's based on the “write once run on every platform” philosophy: you get to “reap” the benefits of cross-platform development; just “work your magic” in any of the web technologies that you're comfortable with and have your app running on all available platforms
  • … with no need to get yourself tangled up in each platform's native development language
  • your app will have a similar UI on all native platforms 
     

And now, the limitations that you need to consider when building mobile apps using PhoneGap:
 

  • by far the biggest inconvenience is the sluggish performance (leading to poor user experience, needless to add); and it's a more than predictable drawback considering that the web was created for web pages, not for heavy, animations-loaded, complex apps
  • you risk to get all the issues of the web, as well, right out-of-the-box, along with your PhoneGap hybrid app. Bugs specific to certain browsers or styles that work differently depending on the browser here included! 
     

In short: on one hand, you get to enjoy a great developer experience, on the other hand, you risk to compromise the user's experience!
 

React Native: Top Pros and Cons

In a PhoneGap vs React Native “competition” the former would always fall behind when it comes to performance: React Native is undoubtedly faster.

And here are some other benefits to "reap" for using React Native to build your mobile app:
 

  • it renders real native components instead of a webview
  • also, since it renders NATIVE views without using webview as an intermediary, expect to face no browser compatibility challenges
  • there's strong social proof, highly relevant evidence for its reliability: Instagram, Airbnb, Uber
  • it's committed to the “learn once, write everywhere” philosophy; once you're familiar with React, you'll be writing native apps in no time, with no need to delve into Java or Objective-C coding, unless you want to extend your app's functionality
  • moreover, React's backed by a huge community, so during your learning time and then during your app development process, you can rely on plenty of “expert” support 
  • the user experience is significantly improved: a React Native app will always have a native look and feel to it compared to a mobile web app 
  • also, since it renders native views, expect smoother, high performant animations, as well
     

Yet, React Native does come with some drawbacks, as well, that might discourage some (even you!):
 

  • you need to be familiar with React, there's way around it
  • you'll need to write an app for every native platform (due to that above-mentioned JS-native platform based structure) since some of the components might be platform-specific
  • don't expect to be able to use HTML: it's native components that you'll need to "juggle with"


And The Answer to “Your PhoneGap vs React Native” Dilemma” Is...

“It depends!”

If you've already used React for the web, so you're definitely not stepping on alien ground, go with React Native!

It would be a pity not to leverage your React knowledge and not to benefit from all the top performance that you get to inject into your mobile app!

Not familiar with React? And, moreover, you love having an entire “palette” of familiar web technologies at hand, to just “grab and use”?

Then you'll love PhoneGap's “developer friendly” approach!

The END! Hope I've included all the most relevant pros and cons and managed to pull off some good explanations on why some developers get seduced by Facebook' baby, React Native, while others prefer to tap into familiar PhoneGap's own advantages.

How about you? Where do you stand now? 

Feb 15 2018
Feb 15

Last' year's “Should I learn Nodejs?” dilemma has turned into an “I'll strive to become a better Nodejs developer!” resolution this year. Nodejs is already developers' “adored” framework and building "the next big thing" in terms of Nodejs-backed apps is the new challenge in 2018! And this definitely calls for a shiny and new set of coding habits to integrate into your Nodejs app development workflow.

New code practices to stick to when writing Nodejs apps, new coding standards that you should follow and techniques to master for using this framework to its full potential. To your future apps' advantage, of course.

Speaking of which, here's a list of 12 Nodejs development pieces of advice for you to consider if one of your resolutions for 2018 has been: “To become a Nodejs padawan!”
 

1. Start to Learn The Basics of Import and Import()

Think ahead of ES modules' current situation. Which is the following:

  • ES modules have been supported since Node.8.5
  • it's true, though, that they're still wearing their “experimental-modules” flag
  • yet they're already being used, intensively, with the @std/esm library (and transpilers)

Do consider learning the basics and be ready to level up from there. Since it's pretty obvious that 2018 has lots in store for the ES modules.

2. Integrate Asynchronous Programming Into Your Nodejs App Development Workflow

There are 2 ways of carrying out your input/output operations and setting up your Nodejs development environment:

  1. synchronously, having your resources blocked for some time 
  2. asynchronously (Node.js' innovative application of asynchronous programming): where tasks can be carried out simultaneously since the resources don't get blocked 

Now just consider a scenario of multiple operations to be performed, where resources keep getting blocked... This would have a dramatic impact on your Nodejs app's performance!

In other words: embrace the asynchronous code!

Use async-await! Turn it into your own “trump card” for handling async events and embrace the simplified version of the once so overwhelming code bases.

3. Modularize Your Code: One of The Very Best Coding Habits to Develop 

Keep it small! Get into the habit of writing “bite-sized” chunks of code replacing the tediously long blocks of code that you might be used to right now.

Here's why:

  1. it will be fairly easier for you to embrace the asynchronous coding philosophy this way
  2. small-sized pieces of code will be easier to handle, adjust and closely monitor both for you and for anyone in your development team 
  3. handling a cluster of bite-sized chunks of code gets particularly convenient when it's a complex Nodejs app development project that you're dealing with

4. Master Containerization & Adopt the Microservice Architecture

Since the Nodejs application architecture is a microservices-based one. 

Therefore, one of the best code practices to incorporate into your workflow is using containers. Containerize your Nodejs apps and streamline your services deployment by tapping into these 2 techs this year:
 

Docker:
 

  • the software technology to generate your containers 
  • … which are nothing less than all-in-one pieces of software encapsulating all the resources that they need to run: system tools, code, runtime, system libraries 
  • containers that will increase your deployments' security level
  • and that you even get to use for simulating production environments locally 
     

Kubernetes
 

  • an open-source system that you get to use for automating everything Docker containers-related: scaling, deployment, containerized apps management...
     

Friendly advice: before you jump straight to containerizing your services, take some time to upgrade your existing code; for this, apply the principles included in the 12-factor app methodology.
 

5. Nodejs Application Performance Monitoring: Make It an Ongoing Process

Especially if it's a complex microservice ecosystem that you need to keep a close eye on!

Monitor your system, using the ever-improving toolbox at your disposal, detect and fix errors before they even get to catch your app users' attention. 

Close and on-going monitoring sure is one of the very best Nodejs app development habits that you could develop this year!
 

6. Mind The Bugs in the Code, That You Might Leave Behind

Be alert and avoid those scenarios where you leave trouble-making bugs behind, as you “knit” your web of code. 

And being alert means:
 

  • tracking your error events
  • detecting errors in their early infancy
     

Note: luckily for you, incorporating this practice into your Nodejs app development process is somewhat easier when using this framework. 
 

7. Get Acquainted With HTTP/2

Again: always be one step ahead of the game! And since we can't but anticipate that HTTP/2 will be going from experimental to stable this year in Nodejs, make sure it won't “take you by surprise”.

HTTP/2 has multiplexing and server push, with a signification impact on the native module loading in browsers.

So, there's no doubt about it: it's going to lose the “experimental” flag, that it has been wearing since Nodejs 8.8, and become the new standard with Nodejs this year.
 

8. Use Semantic Versioning: Another Nodejs App Development Habit to Form 

And this practice is what sets apart a Nodejs padawan from a Node.js... enthusiast.

If you've decided to learn Nodejs this year, make sure you delve deep(er) into its set of best practices (don't just scratch the surface): use semantic versioning for letting the users know that you've updated the app.

To inform them about the actions that they should perform in order to update the app to its latest version.

In short: by updating your packages without SemVer you risk breaking up your precious app!
 

9. Turn Securing Your Nodejs Application Into Your Top Priority

Make sure your Nodejs app is 100% secure above all! Apps' security has been both the vulnerable aspect and the ultimate objective for app developers in 2017.

And 2018 is no different from this standpoint!

Run tests over tests to “challenge” your Nodejs app's security by tapping into all the apps that this framework puts at your disposal:

  • Snyk
  • Data Validation
  • Node Security Platform
  • Brute Force Protection
  • Session Management

If there's a vulnerability there, somewhere, within your app, make sure you track it down before... it gets exploited!
 

10. Adhere to The JavaScript Standard Style for Writing Your Code

Following a set of coding standards will just guarantee you that no big issues will show up later on. In this respect, the JavaScript standard style makes the best choice for your Nodejs app development workflow.

Here's why:

  • you get to “hunt down” style issues and coding errors early in the development process
  • it sets the single space after keywords “rule”
  • it will automate your code's formatting by running standard-fix 
  • it sets the “function name followed by space” standard
  • and the “single quotes for strings” one

11. Put All Your “Require” Statements at the Top 

“Pin” this app development advice right on top of your list of best practices!

It will make all the difference! By grouping all your “require” statements right at the top you'll practically:

steer clear of performance issues, since “Require” is synchronous and it will simply block the executions (thus avoiding ugly scenarios)

Major tip: use Node's built-in module loading system; it comes with a "require" function which will automatically load the modules existing in separate files.

END of the list! These are the top code practices & new “healthy” habits to get into this year for making the most of this framework.

And thus turn your Nodejs app development projects into the next famous apps built with Nodejs!

Jan 08 2018
Jan 08

Ready to set up your web app? One which, needless to add, should deliver your users a feature-rich front-end experience? Great! Now comes the truly challenging part: deciding which JavaScript UI component library — Vue.js vs React —  is right for your web project!

For its specific needs and requirements:
 

  • is it a small or a large scale one?
  • is it one overloaded with dynamic elements?
  • do you plan to go mobile, too?
  • do you want it built fast or do you want it capable to scale up in order to accommodate all future functionalities and features?
     

And the debate is nothing but:

convenient simplicity and lightness vs superpower backed up by a thriving community 

But let's not move away from your initial “dilemma”:

“In a Vue.js vs React competition, where I get to choose the most appropriate front-end framework that should power my future app, which one's the winner?”

Let's bring in the 2 contestants on the “stage” now, shall we?
 

But First: 2 Crucial Questions That You Should Be Asking Yourself Beforehand
 

1. Will it be a web or a native app?

And this is a critical question to be asking yourself way before you start your “investigations” on the 2 competing JavaScript UI component libraries.

Here's why:
 

  1. React has got you covered whether it's a web application (ReactJS), a native mobile app (React Native) or... even a virtual reality front-end app that you're planning to develop. And this is, no doubt, one of the most heavy-weighing answers to the question: “Why React over Vue?”
     
  2. Vue2.0 has made a big step forward, towards a native approach (and here I'm referring to Weex, of course); and even if it still can't get anywhere close to React Native's built-in support for building native mobile apps, it's still a “promise” for the future to come.
     

2. How Much Time Do You Have Till You Need to Actually Start Building It?

In other words: is it an “ASAP” type of app developing situation or you do have the “luxury” to invest as much time as needed in learning a new JS framework?

And this question is more than relevant (and helpful for narrowing your 2 choices down to 1 from the start) since:
 

  1. ReactJS can be discouraging for some, due to its quite steep learning curve; from its terminology to its heavy documentation, everything looks less familiar, less intuitive, more frustratingly complex
     
  2. Vue.js, on the other hand, has “seduced” lots of its current advocates precisely with its low learning curve: it “spoils" them with familiar CSS, HTML, ES6 and where do you add that it doesn't call for a Webpack either.
     

Basically, you get to explore and capitalize upon Vue.js's potential right away, in pretty much any code sharing environment.
 

Go With Vue.JS If...
 

1. It's simplicity in syntax that you value most in a web framework 

In a “Why moving from React to Vue?” debate, the argument of “extreme simplicity” would have to be the strongest one.

That's right, this JavaScript UI framework's simplicity is built deep into its design.

Moreover, the familiarity of the concepts that it uses (or better said “copies” from its main 2 “rivals: React's virtual DOM and Angular's two-way data binding) could be enough to help you find the answer to your “Vue.js vs React” personal debate.

You just run your Vue.js project right from your web browser!

And its simple syntax bubbles up to the easiness of altering the state data (not to mention that this also makes it significantly easier to pick it up). 
 

2. It's a small scale, ideally fast web app that you're planning to build

Since page size is a game changer (isn't it?) when it comes to building an app, Vue.js comes to tempt you with its surprisingly low weight (approx. 25.6KB once minified).

Now you do the math how this will impact the rendering system and, overall, how it will tilt the balance in any “Vue.js vs React speed” comparison.
 

3. You're more into a “templatey” way of building apps

And how could you “resist” a default template structure after all (and even so more if you're not new to AngularJS)? One that uses old-style HTML.

Basically, you get to drop your markup into an HTML file and thus:
 

  • use already familiar (aren't they) HTML attributes for injecting the needed functionality into your default template 
  • use pre-processors
  • clearly separate layout from functionality 
     

… as compared to building your app using ReactJS, which uses a whole different approach: it requires you to put together your own DOM using a JSX syntax.

Note:

  • yet, some might argue though that templating comes at a cost, that of learning the extended HTML syntax, as compared to the rendering functions. And, moreover, that React's JSX syntax puts superpowers in the hands of the developer, once he/she gets familiar with it. Since it enables him/her to use JavaScript in his template.

And yet: stay assured, Vue.js 2 now provides you with both a render functions and a templating option for setting up your web app!
 

Go With ReactJS If...
 

1. You Want to Easily Build an App That Should Work on Both Web and Mobile

Convenience at its best! This is how we might call Facebook's “protegee's” two-faceted nature:
 

  1. ReactJS for building your high-power, interactive web app's interface with
  2. React Native for building your next best thing in terms of native apps
     

No need for you to knee deep in learning the nitty-gritty of a whole new JavaScript UI component library.

Instead, you'll be using the already familiar React for carrying out both your plans (to build a web and a native app), “juggling” with web components and respectively with native components.
 

2. It's a Complex, Large Scale App Project That You Have in Mind

If that's the case, then the following argument might just be a decisive one in your Vue.js vs React “dilemma”.

For React is built with the specific needs of large-scale apps in mind! Which means that it's perfectly equipped for injecting them with high performance!

And it's precisely when you're dealing with an overly complex app project that you realize that:
 

  1. transparency and testability are crucial for you
  2. a template system is way too restrictive, far less configurable (although it would help you get a basic app up and running in no time)
     

In this respect, React's JavaScript-made templates grant you the freedom you need for:
 

  • reusing
  • easily testing
  • restructuring
     

… your conveniently decomposed code.

And this is the “superpower” that React lays in your hands: it allows you to “split” its JavaScript structure into multiple components, that you can easily test and reuse!

It “spoils” you with an ideally configurable rendering system.
 

3. It's a Huge Ecosystem and a Thriving Comunity that you value most 

React's indisputable “fame” — not to mention Facebook's backing — does come with its benefits. Advantages that you can capitalize upon:
 

  1. more resources out there for you to delve yourself in and to leverage in your app (tutorials, articles, Stack Overflow answers etc.)
  2. a wide range of add-ons and tools for you to select from and boost your project with
  3. the guarantee that you'll benefit from a continued maintenance (given by Facebook's patronage and, therefore, by the whole “army” of React developers that commit themselves to keeping it closely
     monitored)
     

And The Winner of This "Vue.js vs React" Dabate Is...

Have I made you even more confused? Is it even harder to state which front-end JavaScript framework would win the Vue.js vs React debate?

One's “seducing” you with a simple syntax and set up, the other one with its scaling capabilities.

One “boasts” with faster rendering if it's a small app that it's powering, while the other one empowers you to build both web and native mobile apps.

And where do you add that the two UI frameworks share a considerably large set of features, as well:
 

  • they're both conveniently lightweight
  • they're both open source
  • they both use virtual DOM and reactive components
  • they both rely on server-side rendering
  • … and are both component libraries providing you with a “backbone” in terms of functionality.
     

So you'll need to rely on third-party frameworks for handling any extra functionality (state management, routing etc.) that you're planning to equip your future app with.

Decisions, decisions...

Now here are a few conclusions deriving from my little presentation here that might help you decide a bit easier:
 

  1. opt for Vue.js if it's a new JavaScript framework that you'd like to drop into an already existing codebase
  2. choose the React library if you're planning to leverage web technologies to develop a native mobile app
  3. go with React if it's an SPA or a really complex, large-sized app that you're planning to build
     

So, is it any easier for you now to solve your Vue.js vs React dilemma?

Sep 22 2017
Sep 22

There's no such thing as “the best web technology” but “the best technology for particular use cases”! For your web projects' particular needs:
 

  • do you want it developed fast or do you want it to work fast?
  • what's crucial for your specific project: that your web technology should scale great or that it should be flexible and IDE friendly?
  • do you value a highly expressive language or one that's the same on the server and on the client's side (for back-end and front-end)?
     

Take some time to answer the above questions. Then see if can find your priority features and the capabilities that you're looking for in a web technology and whether your project fits any of the use cases for Node.js that we'll be pointing out here below. Keep reading...
 

But First: What Is Node.js?

Just a few words about this web technology competing for the “chance” to power your future web project:
 

  • a JavaScript platform or “runtime environment” if you prefer 
  • built to enable you to develop fast and highly scalable server-side apps 
  • comes with a unique I/O model which makes it particularly lightweight and excellent for handling big flows of data (real-time situations handling a ton of requests) 
     

Reasons Why Node.js Is Increasingly Popular 

And here we're thinking about companies such as Uber, LinkedIn and... NASA that saw huge potential in Node.js!

But don't take these brands/enterprise names as unique arguments for jumping on the Node.js trend! Better scan through, ponder on and put the following reasons for why you should be choosing this technology against your own project's needs and particularities:
 

  1. your development team will get to use the same language, both on the client and on the server side (so both on the front-end and the back-end); this can only lead to an efficiency boost and to reduced development costs (since your front-end and back-end developers will then be cross-functional)
     
  2. the same feature practically speeds up the whole development process (parts of your app can get shared and reused from the back-end to the front end and vice versa)
     
  3. Node.js is a full-stack technology: you get everything you need for Node.js to work all in one package, from the HTTP server to the templating engine
     
  4. it's free and open-source technology
     
  5. it loads fast (and here we're comparing it against Ruby on Rails)
     

Use Cases Where Node.js Works Best

1. For Developing Real-Time Apps 

If it's a real-time app that you're planning to build, then Node.js makes THE excellent choice. It's built to:
 

  • make sharing and reusing of library code packages a breeze
     
  • handle heavy loads of concurrent client requests depending on instant response time like no other rivaling technology out there
     
  • speed up the client-server data sync
     
  • process massive loads of data in real time 
     

But let's talk facts!

Meaning specific examples of “apps/sites where:
 

  1. big flows of data need to get processed in real time
     
  2. multiple connections are simultaneously active and requiring immediate response time (relying on asynchronous interactions, like Quora.com for instance)
     

So here it is, our list of real-time app examples, of use cases where Node.js works best:
 

  1. chat apps (instant-messaging, live-chat apps)
  2. collaboration tools: drawing/editing-type apps
  3. e-commerce transaction apps
  4. video conference apps (depending on VoIP and specific hardware to work)
  5. multiplayer games/online gaming apps
     

In short: Node.js isn't the unique solution, in terms of web technology, to develop your real-time app with, yet the: 
 

  • unmatched performance that it will turbocharge your future app with (it can handle big data flows and multiple requests and all this without compromising on page load time)
  • ease of development that it “lures” you with
     

… do put it on top of your potential web technologies to power your app with!

2. For Building Single-Page Apps Heavy on Processing on The Client Side 

Is it a single-page app site that you're planning to build? One of those modern web apps dealing with a lot of rendering, of processing on the client's side mostly (having a back-end playing a single role: providing a JSON API)?

Then you can't choose a more appropriate web technology!

Thanks to its unique I/O model, Node.js is equipped to process high volumes of I/O driven requests and data sharing tasks (e.g. the validation code shared between the client and the server)

In other words: it's a powerful technology “capable” to handle great piles of instant data, of IO-bound requests, one that should scale easily and process the multitude of requests at high speed that you're building, then Node.js is the one for the job!

Note: do keep in mind, though, that if it's more than shuffling data around that you need your web technology to excel at, if there's a lot of CPU processing (e.g. image processing) involved, then you might want to consider other technology for your web project!

3. For Building Streaming-Data Apps

Node.js does a remarkable job, thanks to its capabilities to process massive loads of data in real-time when it comes to supercharging streaming apps.

Let us give you just a few examples of data streamlining tasks where you could leverage Node.js's capabilities:
 

  • encoding files while uploading them
  • uploading files in real-time
  • building proxies between layers of data

4. For Building REST/JSON APIs

Facing the challenge of wrapping web services or data sources (so other data sources) and displaying them via a JSON or a REST programming interface? Node.js will “save the day”, once again!

Since it:
 

  • runs on Javascript 
  • “boasts” with a one of a kind I/O model
     

… it makes the handiest tool/web technology for you to go for whenever it's APIs that you need to build!

Does any of these 4 ideal use cases for Node.js match your own? Do this platform's features and functionalities meet your specific web project's needs? If so: entirely or just partially?

Sep 14 2017
Sep 14

“Teach a man to fish and you feed him”.

In other words: don't expect us to reveal to you, by the end of this post, which is the ultimate winner of this Angular vs React's debate! Which is the right JavaScript technology for your next web project. For we won't!

Instead:
 

  • we'll be helping you weight the 2 widely-used JS frameworks' advantages/disadvantages
  • we'll encourage you to evaluate all their key aspects
     

… so you should be able to answer THE question yourself: “Should I choose Angular or React for my next web project?”
 

Angular vs React: Introducing The 2 Competing Technologies

Before you get to run your “magnifying glass” over these two popular JavaScript frameworks' key strong points and drawbacks, while comparing them against your own web project's requirements, allow us to briefly introduce them into the “arena”:

Angular: a full-stack, feature-reach JavaScript MVW framework

… built so that it can provide you (or your team of developers) with all the needed tools out-of-the-box! Where do you add that:
 

  • it's search giant Google-supported
  • tailored to fit large enterprise teams' specific workflows
  • designed to help you build highly interactive, fast-loading websites and web apps

React: so much more than “just” a JavaScript library for building great interfaces

Otherwise, how could you have even considered comparing it to a full-blown framework like Angular, right?

React is many developers' top choice (and it sure has its own "fan club" within our Toronto web development team here, as well) whenever they're looking for an ideally lightweight, easy to tweak and twist framework for building dynamic, high trafficked (having data that's frequently changing) web apps! 

Now that we've introduced the 2 “contestants” competing for the chance to be powering your new web project, let's go on and highlight their pros and cons (tackling multiple key aspects), so you can evaluate them yourself:
 

Angular Vs React: Comparing 11 of Their Key Features 

1. Performance 

We need to admit that the 2 JS technologies are comparable from a performance perspective. Yet, we can still outline a few performance-impacting features inclining the balance to one side or another:

Angular:

  • it supports caching (along with other processes), which means that the server performs at its best
  • yet, its large size does negatively influence load times on mobile devices   

React: constant components re-rendering can lead to performance issues, especially if it's an app handling a heavy load of data that you're planning to build 

2. Flexibility 

Angular: doesn't allow you too much freedom for customizing your app/website so that it meets your needs in the smallest details

React: highly flexible

3. Development Time

Angular:

  • your development team will need to invest a significant amount of time in understanding the code (there's a whole lot of unnecessary syntax required), in debugging
  • it calls for Angular-specific syntax and 3rd party libraries 
  • its layered, hierarchical structure can be quite discouraging for a developer working with Angular for the first time

React: 

  • its Flux architecture is highly convenient and competitive to MVC
  • is quite easy for developers to understand it
  • the longer time required to set up a React project might look like a drawback to you, yet once you've built your React-powered app adding on new cool features later on is considerably easier

4. Feature Set

Angular: it does come packed with “out-of-the-box” tooling and built-in best practices 

React: although not a full-stack JavaScript framework as Angular, if React will be your final choice you can stay reassured: “when in need”, there's practically a third party library for pretty much everything

5. Scalability

Angular: is built to scale easily, its design, as well as its powerful CLI, being the best proofs 

React: designed to be easily tested and, implicitly, scalable 

6. Learning Curve

Angular: 

  • be prepared to invest significant time resources in learning this over-sized library
  • moreover, learning “just” Angular is not merely enough: you'll then need to get yourself familiarized with MVC, with Typescript...

React:

  • on the bright side: it works with the fewest abstractions
  • on the... less bright side: you'll still need to take your time to learn all the best practices (and there aren't precisely “a few” only)

7. 3rd Party Library Integration

Angular: when it comes to the 3rd party library compatibility aspect of this Angular vs React “debate”, Angular's not doing so well: Typescript demands type definitions for every single library that you'd want to integrate 

React: 

  • it's written on pure JavaScript logic
  • it integrates perfectly with 3rd party libraries (even with the DOM based ones!)

8. Applicability

Angular: used mostly for building enterprise, traditional form apps

React: it usually powers complex, high-performance sites/mobile or web apps featuring complex user interfaces, with multiple events, multiple inputs (each one “risking” to impact the other's screen)

9. Native Rendering

Angular: comes packed with Ionic 2 and NativeScript

React: it's significantly better “equipped” for native rendering thanks to ReactWindows, Next.js, Alibaba, React Native

10. Size

Angular: it does have a substantial size, which inevitably impacts its performance on mobile

React: smaller sized and, implicitly, conveniently lightweight

11. Optimization Goals

Angular: it's aimed at “boosting” the productivity of development teams working within a company 

React: performance, flexibility, and simplicity are this JS technology's main “objectives”
 

And Last: 9 Key Questions to Ask Yourself Before Making Your Choice

Don't rush in to give your own verdict on this Angular vs React debate. Not just yet.

Not before you've asked yourself these key last questions strategically chosen to “cement” your final decision:
 

  1. Do you represent a company or are you a Drupal developer working in an enterprise-level team? Then you're definitely better off with Angular! It's designed to boost large teams of developers' productivity and to adapt to big companies' workflows (just let Angular's CLI outline and guide you along the step-by-step path to take for completing your application!).
     
  2. Are you a start up digital business instead? Then React might just better meet your company's specific needs.
     
  3. Do you have a “secret” weakness for templates? Then Angular is the JavaScript that you'll feel most comfortable working with on your next web project!
     
  4. Do you love Typescript? “Angular” is the answer to your own “Angular vs React” dilemma
     
  5. Do you love “getting your hands dirty” in customization, to be given the chance to tweak your app/website whenever and however you'd like to? React will grant you this freedom!
     
  6. Is high performance a major issue for you? React!
     
  7. Is productivity one of your main goals? Higher placed in your hierarchy than... flexibility, let's say? Angular!
     
  8. Do you have a particular interest in open source web technologies? And does a “guarantor” like giant search engine Google weight a lot in your decision-making process? Then don't “torment” yourself any longer and choose Angular with no hesitation!
     
  9. Do you fancy building an app with complex, eye-catching interfaces, yet one with a small footprint? Then it writes “React” all over your project!
     

We strongly hope this little “questionnaire” here, along with our comparison tackling these two JS technologies' major aspects, will help you make up your mind faster.  Help you make the right decision for your upcoming web project.

Final note: there's no such thing as “THE” perfect choice for each company, development team, project environment, and use case. Not even a “one size fits all” platform for all of your future web projects. Do keep that in mind!

Aug 04 2017
Aug 04

“Progressive Web Apps are experiences that combine the best of the web and the best of apps.” (Google Developers). Brief, to the point, and encompassing, in just a few words, all the reasons why PWAs have gained so much popularity over the last few years!

They sure carry loads of potential to shape the future of mobile web in the years to come!

Now let's try a “guessing game” and see if we can guess why you've chosen to build a progressive web app instead of sticking to optimizing your current site for mobile:
 

  • they're... progressive: they work regardless of the used web browser
     
  • they're not connectivity-dependent: not only that they don't need internet connectivity to run, but they do load fast even in the context of a terrible network performance 
     
  • they run on modern web technologies 
     
  • they're “clusters” of app-like features
     
  • they're installable: users get to add them to their own home screens and to reuse them with a simple click on their shortcuts 
     
  • they're responsive out-of-the-box
     
  • they're not constrained to refresh entire web pages when they're loading new content 
     
  • they send relevant push notifications 
     
  • they load at full-screen
     
  • they grow more powerful with time, as the user-progressive web app relationship “matures”, so to say
     

Moreover (and this is no tiny detail, for sure), to the memorable experience that a progressive web app delivers to the end user, add the benefit of a relatively low-complexity development process!

Speaking of which, here are the 5 best tools to use to build a progressive web app:
 

When you say “web development” you instantly say “JavaScript”, right?

Yet, when you're planning to set up a progressive web app you should be more specific than that: you should “laser-focus” on one of its many tempting frameworks! 

In this respect, here are the 3 ones that we recommend you to consider! Select your suitable core framework depending on factors such as your future app's complexity or the time limit that you need to adapt your workflow to:

Angular.JS

Pros: 

  • probably one of the most powerful JavaScript frameworks for building web apps
  • the environment that its newest version, Angular 4.0, provides is the same for both for mobile and desktop web development 
     

Con: 

  • although there are plenty of tutorials out there that you could use, you might still find this framework to be too complex in case you want to build a progressive web app with just basic features and functionalities

React

By far this framework's most “seducing” feature is its component-approach to web development!

Practically all the components putting together the UI are JavaScript-based, which enables you to easily reuse them at need! A powerful UI development speed-booster tool!

Besides its component-centered approach we could easily point out a couple of other reasons for choosing React to power up your progressive web app with:
 

  • giant Facebook supports it (and along with it all its worldwide users, which are constantly testing it, as a global-scale)... need we add more?
     
  • it's React Native's foundation, meaning that you'll be able to easily and seamlessly port your React-powered apps to native apps
     
  • thanks to the component-based UI, you practically get to deliver your future progressive web app to any browser, device or operating system; using Node.js and Reactive Native, those components can render both in the browser, on the server and inside the apps themselves

Polymer 

Now when time is a “merciless” projection of your client, Polymer makes the perfect choice of core framework to build a progressive web app!

It “spoils” you with:
 

  • templates
  • reusable components
     

… which stand for the perfect definition of a “fast app development process”! 

Creating prototypes is, no doubt, the perfect use case for this framework! You can just make use of the template that Polymer provides you with for setting up the code of your app project and add on the client's input later on in the development process!

There's more! Since “fast” is the defining characteristic of this framework, where do you add that Polymer uses PRPL pattern for speeding up the app's delivery to the chosen device?

Should we mention, as well, that the template features the Google-emblematic material design out-of-the-box?
 

2. Webpack: An Essential Tool to Build a Progressive Web App, a Custom One

If the aforementioned Polymer makes a great choice for getting started, for setting up your apps's prototype, then Webpack gives you access to the next level! The one where you build a progressive web app that's more complex and front-end driven.

Its two major benefits:
 

  1. it's a module bundler: it enables you to bundle your JavaScript resources (even fonts, CSS, images and other non-code assets), which will get treated as JavaScript objects, meaning that they will load significantly faster
     
  2. it simplifies the whole creation of dependency graphs (you'll no longer need to display the links to all your JavaScript files on your HTML page)
     

In short: managing dependencies gets so much more streamlined with Webpack

Con:

  • along with its speed-enhancing features, Webpack comes with a quite steep learning curve. A manageable one, though, if you consider all the learning resources and documentation available online (that aren't beginner-friendly though, so get ready to invest some resources of time for learning your way around this JavaScript module bundler)!
     

If it's a lightweight, yet functionality-loaded, quick to set up progressive web app that you have in mind, then Knockout is the framework to go for!

Here are some of the powerful features that make it an indispensable asset for your toolbox:
 

  • it comes with a light library (13 KB), yet carrying a heavy load of functionalities
     
  • you get to “inject” its library into an existing website without extensive rewrite
     
  • it's easy to learn
     
  • it provides you with templating, meaning that building complex apps gets significantly faster (no more duplicated DOM elements)
     
  • it works exclusively on JavaScript (making your future app accessible from any browser, any framework)
     
  • it's great for handling MVVM bindings between HTML and JavaScript
     
  • it enables you to extend your HTML
     
  • it comes with a load of pre-built attributes (so you won't need to write them, yourself, like it's the case with other “rivaling” frameworks)
     

And this is how our suggested “arsenal” of tools to build a progressive web app looks like! Keep in mind, though, that this is an ever-changing list, considering the fast pace at which new web technologies emerge in the digital landscape!

May 10 2017
May 10
May 9th, 2017

DrupalCon is many things to many people. For me, this year’s North America DrupalCon in Baltimore was a chance to connect with my remote co-workers in the same place, help share knowledge while learning things myself, and celebrate all the things that Drupal makes possible.

The Drupal 8 with React.js and Waterwheel Training

Our first big event was “API First Drupal 8 with React.js and Waterwheel Training”, where Web Chef Luke Herrington took a canonical JavaScript application—a todo list built with React—and hooked it up to Drupal 8 through a new JavaScript library called Waterwheel.js. Todos were stored in a headless Drupal site via the JSON API module, and we even provided a login page and a `like` button for todos. Although we had a small army of Web Chefs available to help, Luke had created such a great training that our extra support wasn’t needed, and the attendees were really able to dive deep into how everything worked.

Future of the CMS: Decoupled

“I’ve completely rewritten my talk,” said Todd, the Four Kitchens CEO, at the team dinner on Monday night. I’ve seen him give this talk before but this declaration really piqued my curiosity.

There were a lot of talks at DrupalCon about the “how” of decoupling, but Todd’s revised talk is a great summary of the “why”. In it, Todd talks about the differences between CMSes being “content management systems” versus “website management systems” and about how that content can be managed so that it is reuseable on all categories of devices. Because the technology is always changing, it’s a talk he rewrites at least once a year, and I’m glad I got to see this version of the 2017 talk when I did.

Supercharge Your Next Web App with Electron

To show off his work in Electron, Web Chef James Todd brought two drawing robots to DrupalCon that he set up in our booth. Each machine was powered by RoboPaint, a packaged-up web app. I’ve been curious about Electron for a while, and when I learned that James was giving a talk on the subject I immediately reached out to help him build his slide deck so that I could learn more. His presentation was thorough and entertaining, and he encouraged people to “experiment and play with it, it’ll be fun”.

Drinks with a Mission

The Drupal community believes that open source technology has the power to improve the lives of others, so instead of the usual DrupalCon party, this year, Four Kitchens teamed up with Kalamuna and Manatí to host “Drinks with a Mission”.

We started the night by asking, “If you had a magic wand that would fix a problem, what problems would you fix?” Answers were written down on post-it notes, which were then sorted into groupings, and finally assigned to teams. Each team took their topic, such as How to Better Connect with Nature, and had to come up with solutions to the topic problem. Great ideas can begin in unexpected places, and the ensuing solutions were as thoughtful as they were hilarious.

Watch the recorded stream of the event: Part 1, Part 2

Taking the Train Home

In the last few years I’ve started to become enamored with the concept of “taking the train”. So at the end of DrupalCon I got my wish, and instead of flying, I spent an entire day traveling by rail: from Baltimore, through Philadelphia’s gorgeous train station, and then on to home in the middle of Pennsylvania.

Recommended Posts

  • A mostly full report on what went down last week in the Big Easy, gonzo journalism -style.
  • Fun & Games DrupalCon Baltimore is next week and we’re so excited to get back together in Baltimore! As the official Drupal Games sponsors, we take fun very seriously and…
  • "API First" or, as some may call it, "Decoupled Drupal", remains a topic of much discussion among the Drupal community. Here are just a few sessions being presented at Drupalcon…
Randy Oest
Randy Oest

Randy Oest is an avid Star Trek fan, plays too many board games, and bought his mother an iPad so that he wouldn't have to fix her computer anymore.

Apr 24 2017
Apr 24
April 24th, 2017

Making Huge Strides Back to Desktop

So what is this Electron thing everyone keeps talking about? Even if you haven’t heard of it, you may have used it! With over 4 millions daily users on Slack’s business oriented chat system, their cross-platform desktop application helps them reach their users outside of browsers, but these systems are in fact part of the same thing.

Back in May 2014, prolific bastions of open source and $2b valuated company, GitHub, took the custom application wrapper it originally created for its Atom code editor and released into the world—and Electron was born. Rebranded from “Atom Shell” in 2015, Electron began to take off almost immediately, allowing regular web developers the ability to make native-like, high performance desktop applications using the exact same HTML, CSS, and JavaScript technologies they use to make the rest of the web.

Piggybacking on the huge wave of API first work in Drupal 8 utilized via the Waterwheel client wrapper, building with Electron allows you to create nearly native desktop experiences using frameworks like React, Redux, Angular, or anything else that your team can construct to run in a web browser. Beyond even that, Electron gives JavaScript direct access to low level Node.js and operating system APIs, allowing your application direct file access, running custom binaries for data processing, execution of alternative scripting languages, serial port or hardware access, and tons more.

Supercharge Your Next Web App

This year at DrupalCon Baltimore, we present “Supercharge Your Next Web App with Electron”, a session that digs deep and covers everything you need in order to dip into the waters of Electron. We’ll talk about what big companies have already taken the plunge and even provide a checklist for when not to move from the web to a desktop app.

Though an Electron app may not be the right choice for your next application, knowing what tools are available to you—and understanding their incredible possibilities—is going to serve you anytime you’re  considering user-oriented frameworks. Don’t miss out on this interesting view into a future of low-energy/high-return desktop applications in the DrupalCon Horizons track this year.

And, during active exposition hours, make sure to come over to the Four Kitchens booth to see a live demo of an Electron app powered by JavaScript—we build a robot artist!

Four Kitchens: We make content go

Recommended Posts

  • In this issue: Launching the new EW.com, MeteorJS; plus Sane Stack, Herp Derpsum, and switching to Sublime Text 3.
  • Fun & Games DrupalCon Baltimore is next week and we’re so excited to get back together in Baltimore! As the official Drupal Games sponsors, we take fun very seriously and…
  • "API First" or, as some may call it, "Decoupled Drupal", remains a topic of much discussion among the Drupal community. Here are just a few sessions being presented at Drupalcon…
James Todd
James Todd

James tinkers with hardware, software, and everything in between.

Events

Blog posts about ephemeral news, events, parties, conferences, talks—anything with a date attached to it.

Read more Events
Apr 18 2017
Apr 18
April 18th, 2017

Fun & Games

DrupalCon Baltimore is next week and we’re so excited to get back together in Baltimore! As the official Drupal Games sponsors, we take fun very seriously and this year you can be sure to find some exciting things to do at our booth—we won’t spoil the surprise but let’s just say you’ll get to see some of us IRL and IVRL.

And if you visited us last year, you know we are all about that Free Throw game. Our undefeated Web Chef, Brian Lewis, will be there to take on any challenger. We’ve all been practicing and we are READY. Are you?

We’ll also have some of our widely-enjoyed Lightning Talks during lunch intervals right at our booth! Learn something new in just a few minutes, howbowdat? Stop by our booth to check out the schedule.

Web Chef Talks

It’s been an exciting year and the Web Chefs are ready to drop some knowledge, including:

Future of the CMS: Decoupled, Multichannel, and Content-as-a-Service, presented by Four Kitchens Co-Founder and CEO, Todd Ross Nienkerk.

Supercharge Your Next Web App with Electron, presented by Web Chef engineer, James Todd.

Why Klingon Matters for Content: The Secret Power of Language, presented by our content specialist, Douglas Bigham.

Training: API First Drupal 8 with React.js and Waterwheel, a training with JavaScript engineer, Luke Herrington.

Party with a Purpose

Last—but definitely not least—you’re cordially invited to our official DrupalCon gathering, Drinks with a Mission, hosted by Four Kitchens and our friends at Kalamuna and Manatí.

Join us on April 25th at Peter’s Pour House from 6-9pm for lively conversation, free-flowing libations, and a structured forum for hashing out ideas on how to use Drupal to overcome the challenges many of our communities face in today’s national and global political climate.

RSVP here!

See you in BMD!

Oh! The kittens are coming along to Baltimore as well—four of them to be exact—and we can’t wait to reveal this year’s DrupalCon t-shirt design. We’re not kitten around. We wish we could show you right meow.

P.S. Check out the 10-day Baltimore weather forecast.

Recommended Posts

Lucy Weinmeister
Lucy Weinmeister

Lucy Weinmeister is the marketing coordinator at Four Kitchens. She loves to share all the new and exciting things the Web Chefs are cooking up at 4K. She is forever reading a book.

Events

Blog posts about ephemeral news, events, parties, conferences, talks—anything with a date attached to it.

Read more Events
Feb 27 2017
Feb 27
February 27th, 2017

Drupal at the Beach.
(The Very Windy Beach)

Every year in February, Drupalers from across the country travel to San Diego to get away from the harsh winter and enjoy the perfect 72 degree California weather. Attendees visit Pacific Beach, walk down the boardwalk, and sometimes even go sailing.

Picture of former Web Chefs sailing.Former Web Chefs Matt Grill and Dustin Younse sail through Mission Bay after a weekend at SANDCamp 2016.

This year, however, attendees were met with … a little weather.

San Diegans, like myself, always find weather surprising and novel to the point where any time it rains for more than 10 minutes, we describe it as “really coming down”. But this time it really was pouring. 75 mph gusts of wind, cloudy skies, and a strong atmospheric river causing record rainfall. Drupal was not at the beach this year.

Weather map showing storms over San Diego.SANDCamp 2017: A little weather.

Drupal Near the Beach

Falling in mid-February every year, SANDCamp affords many speakers the opportunity to field test trainings and sessions before they’re given at DrupalCon.

Drupal 8 with React.js and Waterwheel.js

With the help of my fellow Web Chefs, I presented the first iteration of my training API First Drupal 8 with React.js and Waterwheel.js which I’m happy to announce will also be given at Drupalcon Baltimore! In the training, we took the canonical JavaScript application, a todo list built with React, and hooked it up to Drupal 8 through a new JavaScript library called Waterwheel.js. Todos were stored in a headless Drupal site via the JSON API module and we even provided a login page, and a like button for todos. Overall, the feedback on the training was excellent. People enjoyed learning how to turn Drupal 8 into a world class content API while also getting their feet wet with a frontend JavaScript framework like React. I’m looking forward to improving the training and giving it at Drupalcon Baltimore this year.

Every Project is a Story

One notable session was Dwayne McDaniel’s talk Every project is a story: Applying storytelling to your client interactions in which he explained how the patterns that form good stories, form good projects, budgets, and discoveries. Dwayne explored these story structures and how they can help translate clients’ and stakeholders’ dreams into real plans.

Kalastatic

The session that caught my interest the most was From Prototype to Drupal Site with Kalastatic. Through a case study, Crispin explained the benefits of component driven design and showed off an open-source framework Kalamuna built called Kalastatic. It’s a kss-node driven static site framework for building prototypes and living style guides that integrate with Drupal. It’s a tool very similar to Emulsify, Four Kitchens’ component-driven prototyping tool and Drupal 8 theme. It is great to see the Drupal community converge on component driven development as a solid pattern for building frontends.

Keynote Surprise!

Due to the inclement weather California was experiencing that week, the scheduled keynote speaker, Darin Andersens, had his flight cancelled and couldn’t be there. Luckily Todd, Four Kitchen’s CEO and Co-Founder, always has a keynote in his back pocket. He fired up his laptop and gave his talk on The Future of The CMS, pontificating on where the web is going and what CMSes like Drupal must do to stay relevant.

Always Be Keynoting. https://t.co/OIqmOBur3L

— Four Kitchens (@FourKitchens) February 17, 2017

Thanks, SANDcamp!

Maybe I’ll see you at SANDcamp next year! Also, if you’ll be at DrupalCon Baltimore, sign up for my training API First Drupal 8 with React.js and Waterwheel.js, and check out the other Four Kitchens Web Chefs, too!

Recommended Posts

Luke Herrington
Luke Herrington

Luke Herrington writes JavaScript for work and for fun; he enjoys hacking on new technology and reading about the ethics of artificial intelligence.

Nov 24 2016
Nov 24

There, there, no need to get yourself stressed out over all the new Javascript libraries trying to lure you with their irresistible features. It's impossible even to test all of them!

Why should you allow this whole array of equally tempting choices to “sabotage” your efficiency by keeping you from creating new amazing websites and innovative web apps?

So, how can you keep your focus? By keeping a close eye on these 10 (lesser known) JavaScript libraries that we're convinced that will gain popularity and become the 10 most influential ones in 2017.

Find out what our predictions rely on!


 

1. Node.js

A bit sick and tired of hearing everyone in the web community keep talking about Node? No wonder it's one of their main topic:

  • it's one of those JS libraries that keeps on growing and growing at a mind-blowing speed, no doubt about that
  • it makes that reliable “boost”, the ideal environment, for any developer to get his web development project started with
  • it turns local packages management into a “child's play” in the command line
  • it eases your unit testing (in Mocha.js) work
  • it puts the Sails.js framework at your disposal for building your front-end interface

2. Riot.js

Now here's another JS library that will be wrapped in glory in 2017! Mostly front-end developers will get all excited around it!

Where will the excitement come from? Its helps you create powerful digital interface libraries!

But what makes it a strong alternative to React, one that you should even consider?

Here are just 3 answers to this legitimate question:

  • the whole community of developers backing up Riot.js, that you get to rely on, will make getting the answers to your questions much more time-efficient
  • its simple syntaxh makes it easier for you to control it while you're access DOM
  • it makes the perfect choice for customizing the elements of your app

3. Keystone.js

We could say that Node.js “passes on the torch” to Keystone.js.

Once you've used all of Node.js' capabilities in your web development process, reach out for Keystone. It will empower your website/web app with a 100% JavaScript, full-scale CMS engine!


 

4. D3.js

What do you currently rely on for creating eye-pleasing visualizations of your data?

Whatever you're using, you should definitely let D3.js stir your curiosity. 

It has no rival among the JavaScript visualization tools. It will help you add the modern edge to your graphs, dynamic visualizations and charts in no time.

Give it a try! Don't let the trends in the big data industry pass you by, be the one who crafts the trends!  

5. Create.js

On a constant look for the best toolkit to rely on when you create all your web animations and digital media “awesomeness”? 

Well, you should consider Create.js for the role of “assistant” in your work. It's so much more than just “another JavaScript library”: it's a whole collection of libraries in fact. Each one of these “sub-libraries” spoils you with certain features and help you target certain parts of your digital media projects, so that that you should pick the ones that specialize on what you want to achieve in 3D. 

For instance, one library/feature will help you build custom animations for the web, while others will help you handle the HTML5 canvas elements. Got the idea? 


 

6. Meteor.js

What's your future web development/web design project? And your second one? How about the third one in your schedule?

Well, learn that you can practically build all these platforms on Meteor! All of them, plus the ones that are still in the phase of ideas populating your imagination!

Being an open source project, it empowers you with unlimited freedom of creation and innovation. From chat apps, to social media platforms, from custom dashboards to social voting website you can build anything from the ground up on Meteor and React.

Unlimited possibilities? Who could say no to that?

It's true though that Meteor is for the skilled web developers, it's not one of the easiest JS libraries to learn! Therefore, expect to have your brain muscle challenged a bit before you get to play with its whole array of great features!


 

7. Vue.js

Are you in the Angular fans team or in the Ember addicts team?

Now what if I told you that a new “actor” will be stepping on the stage and stealing the spotlight: Vue.js?

For front-end developers it will be more than just “lucky no. 3”. It's a MVVM front-end framework and it's Javacript (how else!)! Therefore, it steps away from the standard MCV architecture.

Although learning it might turn out to be quite a challenge, don't let that discourage you: this is going to be the two typical front-end frameworks' (Amber and Ember) big “rival” in 2017, so you'd better be one step ahead of trends and start learning it now!

8. WebVR

How's your VR projects coming along? 

JavaScript comes to streamline your workflow with its' new API made for VR in your browser. 

It's still under testing (and being an open source you can just imagine the “army” of developers testing all its weaknesses, checking how it works on VR devices and in the latest browsers), but even so, dare and rely on our prediction: you want to keep an eye on it in 2017!


 

9. Chart.js

Name a type of chart that you need to integrate in your website/web app and we'll tell you that you can easily put it together with Chart.js.

Besides the cool data graphs that you can build, we've put this Javascript library on our list due to its other tempting features:

  • it's so easy to customize 
     
  • it's easy peasy to set it up, too
     
  • it comes already upgraded with great options for animations
     
  • it's an open source, meaning that you gain access to helpful documentation, too!

10. Three.js

And here's a more than useful JavaScript resource whenever you feel the urge to pull off some:

  • unbelievably realistic motion-sensitive backgrounds
  • mind-blowing 3D effects
  • amazing 3D web graphics

Don't you look forward to 2017 now, knowing what cool JavaScript libraries will get perfected and ready to help you enhance your full potential as a developer?

Jun 29 2016
Jun 29

This one tripped me up on a recent Drupal 8 project.

Easy to miss when you're working in a development oriented environment with things like JavaScript preprocessing turned off.

A JavaScript file was being added just fine with aggregation turned off, but not getting added with it turned on.

While working on a Drupal 8 client project we were using our module's .libraries.yml file to add a custom plugin for Jquery Validation. Our plugin was using the Moment.js date library to add strict date checking so we could check for overflows. The default date validation in that plugin treats dates like 55/55/5555 as valid - because they are cast to valid JavaScript dates by the browser. We needed to detect overflows and report an error.

It was working all fine locally, but when I sent a Pull request, it didn't work in the Pull request environment (we have per pull-request environments).

After some head scratching I found the issue.

My libraries.yml definition looked like this:

moment_date:
  version: VERSION
  js:
    js/moment_date: {}
  dependencies:
    - clientside_validation/jquery.validate
    - mymodule/moment
    - core/modernizr

If you picked it, I've missed the .js suffix on the file name.

Locally I was working with developer optimised settings, so I had a settings.local.php with the following

$config['system.performance']['js']['preprocess'] = FALSE;

i.e. I was disabling JavaScript aggregation so I could rapidly iterate, something you'd normally do.

Problem was on the Pull Request environment JavaScript aggregation is turned on (as it should be).

And mysteriously this made a difference.

My libraries.yml file was just plain wrong, it should have been

moment_date:
  version: VERSION
  js:
    js/moment_date.js: {}
  dependencies:
    - clientside_validation/jquery.validate
    - mymodule/moment
    - core/modernizr

But with JavaScript aggregation turned off, my webserver was adding the file, sending moment_date.js when moment_date was requested - silently hiding the bug from me.

A tricky one, but one worth sharing.

Drupal 8 libraries JavaScript
Mar 11 2016
Mar 11

Since jQuery’s initial release more than eight years ago, it has grown in popularity among web developers and clients alike – nowadays jQuery is considered to be the foundation of the modern Web. In these past eight years the cross platform library was bundled with countless developer tools, sites and of course, with JavaScript. Now it’s time for jQuery 3.0.

jQuery 3.0 is released

jQuery 3.0 was just released – this version of jQuery has been in planning since October 2014. jQuery 3.0 is a much faster, slimmer version of the old one with great attention given to compatibility. All the old IE workarounds have been removed and more powerful modern API’s were implemented.

Upgrading to jQuery 3.0 is easy

Upgrading to 3.0 is relatively easy and jQuery even released a neat little guide which you can follow. Not only that but with the use of jQuery’s Migrate 3.0 plugin you’ll be able to see any compatibility issues in your project or code.

The new jQuery 3.0 is slim

In the future you won’t really have to use AJAX, you’ll simply be able to use a standalone library that focuses on AJAX requests or a combination of class manipulation and CSS for web animations. The 3.0 version also features a slim version which removes all AJAX and effects modules – this version also excludes any deprecated code. Web developers are of course able to include or exclude any modules they want, thanks to the custom build API used by jQuery 3.0.

Since it’s a very fresh release, there are a few necessary tweaks which will be made in the following months – jQuery Mobile and UI currently have some issues.

Changes and features in 3.0

 

IE workarounds are removed

The old workarounds and hacks for IE9 got removed in order to make jQuery 3.0 sleeker and faster. If you still need support for IE 8 you’ll just have to use the 1.12 release because versions such as 2.0 don’t offer full support for older versions of Internet Explorer.

jQuery 3.0 runs in strict mode

Since most browsers supported by jQuery 3 also support strict mode the new release has been built with it in mind. Your personal code is not actually required to run in strict mode and you don’t need to rewrite your existing code if you want to migrate to version 3.0. Strict mode can work with non strict mode and vice-versa – the only exception is related to some versions of ASP.NET.

A new API for animations

The request AnimationFrame() API is now used for animations, thus making them much faster and smoother. jQuery 3.0’s new API is only used with browsers that fully support it – other browsers such as IE9 will use the older API in order to display animations.

Escaping strings with special meaning got easier

The jQuery.escapeSelector() method allows web developers to escape characters or string that have a different meaning in CSS in order to use them in a jQuery-selector. Example:

„If an element on that page has an id of „abc.def”, it cannot be selected with $(„#abc.def” ) because the selector is prased as „an element with id ‚abc’ that also has a class ‚def’. However, it can be selected with $(„#” + $.escapeSelector( „abc.def”) ).”

Class manipulation supports SVG

Although jQuery 3.0 doesn’t fully support SVG, the methods that manipulate CSS class names such as .hasClass() and .addClass() can be used for SVG documents. Web developers are now able to find and modify classes with jQuery in SVG then style these classes with CSS.

Deferred objects are also compatible with JS promises

JavaScript Promises are a special type of objects usually used for asynchronous computations – these have been standard in ECMAScript 6 and their features and behaviours are specified in the Promises/A+ standards.

In the new version of jQuery deferred objects are compatible with the Promises/A+ standards. Deferreds are also chainable objects, which means it’s possible to create callback queues.

With the new release of jQuery the asynchronous callback functions executions are changed – Promises allow web developers to write asynchronous code that is more similar in logic to synchronous code.

Mar 03 2016
Mar 03

Web development experts tend to debate a lot when it comes to Javascript vs jQuery. There is really no correct answer in this situation simply because either of them can be used to create approximately the same effects or results - it’s contextual.

Generally speaking, jQuery should be enough for your average web development project but in certain cases JavaScript may be necessary to successfully complete it. As a rule of thumb, every web developer should learn both jQuery and JavaScript so let’s get down to the details:

Javascript

Javascript is a web programming language that’s oriented on objects. The programming language is usually used to introduce certain functionality into web pages. The Javascript code is automatically loaded by the browser. Javascript is very similar to C when it comes to syntax – it’s very popular among programmers because you can create scripts for multiple activities such as adding effects or creating menus on certain page elements.

Asynchronous Javascript and XML, also known as AJAX is becoming more and more popular in the programming world. With this technique, HTTP requests are made in the background, without needing to reload the page – changes to certain sections of the page are done in real time. When using AJAX, programmers can create interfaces with limited response time simply because the time for reloading a HTML page is removed.

jQuery

jQuery was released back in 2006 as a library build with Javascript – jQuery helps web developers load dynamic content onto pages, handle events, manipulate CSS and animate certain page elements. If you’re using jQuery you won’t have to worry about how browsers interpret the code. jQuery is a very useful Javascript library that reduces vague code and collects functions which in turn increases your programming workflow.

jQuery 1.x is supported by Internet Explorer 6 or higher and all browsers in general. With jQuery 2.x, the support for IE 6-8 was dropped but instead jQuery supports Internet Explorer 9 or higher.

The jQuery user interface is a collection of GUI Widgets, visual effects and themes created using jQuery, HTML and CSS.

jQuery UI effects include:

Add Class, Toggle Class, Remove Class, Switch Class
Color Animation
Effect
Hide, Show
Toggle
 

jQuery UI Widgets include:

Accordion
Autocomplete
Button
Datepicker
Dialog
Menu
Progressbar
Selectmenu
Slider
Spinner
Tabs
Tooltip
 

jQuery UI utilities include:

Position
Widget Factory
 

Javascript code:
function backgroundChange(color) {
document.body.style.background = color;
}
Onload=” backgroundChange(‘blue’);

Where as in jQuery the code is much simpler and clean:

$(‘body’).css(‘background’,’blue’);

Javascript vs jQuery – Which one to use?

For most web development projects jQuery will suit your needs just fine but as stated before, learning both Javascript and jQuery can be an asset. Keep in mind that one of the biggest differences between Javascript and jQuery is the fact that jQuery can work with many browsers automatically while JavaScript has cross browser compatibility issues due to poor implementation practices.

Jan 05 2016
Jan 05

We’ve been thinking about code reviews lately here at Advomatic.  Fellow Advo-teammate Oliver’s previous post covered the whys of our code review process, and Sarah covered the hows when she did a overview of some tools we use regularly.  This post focuses on the front-end side, and deals more with the whats of front-end code review… as in:

  • what are our main overall goals of the code we write?
  • what are the common standards we follow?
  • and what quick-and-easy changes can we make to improve our front-end code?

Guiding Front-end Coding Principles

In the world of front-end development, it seems like there is an intimidating, constantly expanding/changing set of tools and techniques to consider.  The good news is that there is a pretty dependable set of widely accepted working guidelines that aren’t tool-specific.  We really try to consider those guidelines first when we are reviewing a peer’s code (and the technical approach they have taken):

  • Write valid, semantic HTML5 markup – and as little markup as needed
  • Enforce separation of content, functionality/behavior, and presentation
  • The site should function without the use of JavaScript, which when added, is only used to progressively enhance the site. Visitors without JavaScript should not be crippled from using the site.

Best Practices

Sometimes there are a million ways to solve a single problem, but I think we do a good job of not pushing a particular tool or way of dealing any of those problems.  Instead, we’ll see if the code is efficient and if it can stand up to questions about its implementation, as far as best practices go.  For example:

  • Is there logic-related PHP in templates that should be moved to template.php?
  • Can JS be loaded conditionally from a custom module or the theme’s template.php via
    $render['#attached']['js']
    

    so it doesn’t load on pages that don’t need it?

  • Is the project already using a DRY CSS methodology elsewhere?  BEM or SMACSS maybe?  Should it be used here?
  • Are we generally following coding standards?
  • Are we coding with web accessibility guidelines in mind?

Minimal Effort Refactoring or “Grabbing the Low Hanging Fruit”

Refactoring code as an afterthought (or as a reaction to some problem down the road), is never fun – it pays to be proactive.  Ideally, we should always be retooling and improving our code as we go along as we get more information about the scope of a project and if the project budget and/or timeline allows for it.  When we look at a peer’s code changes, what kinds of things can we suggest as a quick and easy “upgrade” to their code?

  • Markup:
    • Instead of that ugly Drupal-default markup we’re working with, can it be swapped out with an appropriate HTML5 replacement element?
    • Is that inline JS or CSS I see in the markup?  Crikey, what’s that doing here?!?
    • Do we really need all these wrapper divs?
    • Is this the bare minimum markup we need?
  • CSS/Sass:
    • Can we use an already-established Sass mixin or extend instead of duplicating styles?
    • Is this element styling worthy of a new mixin or extend that can be reused on other elements, either now or in the future?
    • Should this mixin actually be an extend (or vice versa)?
    • If the code is deeply nested, can we utilize our CSS methodology to make the selector shorter, more general, or more concise?
    • Is this selector too unique and specific?  Can it be generalized?
  • JS:
    • Does this work without JS?
    • Is there a chance this could adversely affect something unrelated?
    • Does it need to be more specific, or be within a Drupal behavior?
    • In Drupal behaviors, do selected portions of the DOM use the “context” variable when they should? For example:
      $('#menu', context)
      
    • Is jQuery Once being used to make sure that code is only run once?
    • Should this code only run when we are within a certain viewport size range (a breakpoint)?
    • Does it need to be killed/destroyed when the breakpoint changes?
    • Would this functionality benefit from being fired via feature detection, especially if our target browsers are old-ish?

Quick Browser QA

I know, I know.  Browser QA is not really “code review”.  However, it does go hand in hand, and makes sense to deal with when you’re reviewing someone’s code.  It is at that point that you, the code reviewer, are most familiar with your peer’s work and specific goals.

While we do a more thorough and complete test and review of work in target browsers and devices at the end of an iteration (generally every two weeks), we also do a shorter burst of quick QA during an individual ticket’s code review.  We’ll quickly check it in the latest version of major target browsers/devices – this helps us find bugs and issues that are big, visible and easy to fix.  It also ensures that they don’t pile up on us to deal with during our final iteration… which can be really demoralizing.

Back to Basics

Code reviews are great for brushing up on the basics when other parts of your work can seem very complicated.  None of this is particularly revolutionary – it helps to revisit the basics of why you do what you do from time to time. Aside from reviewing the technical aspect of the work, you can act as an outsider that can see the big picture of how this work affects the user experience… easier than someone in the trenches.  This is an important and valuable role to play as things come together on the front-end of your project.

Sep 12 2015
Sep 12

UPDATE 2015-12-04 : Tinytest is now documented, for the upcoming Meteor 1.3 release. See the official README.md. Better use the official information than my unofficial cheatsheet.

I've been doing a lot more Meteor these days, especially working on Drupal 8 SSO with Meteor, and could not find a reasonably complete and up-to-date (for Meteor 1.1.0.3) list of the Tinytest assertions, so I updated, reordered, and completed the existing gist on the topic.

So here is the Meteor Tinytest cheatsheet: : complete list of assertions and helpers for your test methods.

Jul 20 2015
Jul 20

Zoltan (Zoltanh721) recently blogged about WebRTC for the Fedora community and Fedora desktop.

https://fedrtc.org has been running for a while now and this has given many people a chance to get a taste of regular SIP and WebRTC-based SIP. As suggested in Zoltan's blog, it has convenient integration with Fedora SSO and as the source code is available, people are welcome to see how it was built and use it for other projects.

Issues with Chrome/Chromium on Linux

If you tried any of FedRTC.org, rtc.debian.org or meet.jit.si using Chrome/Chromium on Linux, you may have found that the call appears to be connected but there is no media. This is a bug and the Chromium developers are on to it. You can work around this by trying an older version of Chromium (it still works with v37 from Debian wheezy) or Firefox/Iceweasel.

WebRTC is not everything

WebRTC offers many great possibilities for people to quickly build and deploy RTC services to a large user base, especially when using components like JSCommunicator or the DruCall WebRTC plugin for Drupal.

However, it is not a silver bullet. For example, there remain concerns about how to receive incoming calls. How do you know which browser tab is ringing when you have many tabs open at once? This may require greater browser/desktop integration and that has security implications for JavaScript. Whether users on battery-powered devices can really leave JavaScript running for extended periods of time waiting for incoming calls is another issue, especially when you consider that many web sites contain some JavaScript that is less than efficient.

Native applications and mobile apps like Lumicall continue to offer the most optimized solution for each platform although WebRTC currently offers the most convenient way for people to place a Call me link on their web site or portal.

Deploy it yourself

The RTC Quick Start Guide offers step-by-step instructions and a thorough discussion of the architecture for people to start deploying RTC and WebRTC on their own servers using standard packages on many of the most popular Linux distributions, including Debian, Ubuntu, RHEL, CentOS and Fedora.

Jul 06 2015
Jul 06

Adding a map to a Drupal 7 site is made easy by a variety of location storage and map rendering modules. However, at the time of this post most of these modules don’t have an 8.x branch ready and therefore aren’t usable in Drupal 8. Update: As of October 2016, the Leaflet module has a beta release for Drupal 8. Since Savas Labs has recently taken on a Drupal 8 mapping project, we decided to use the Leaflet library within a custom theme to render our map and the Views GeoJSON module to store our data.

Before we jump in, I have to give major kudos to my coworker Tim Stallmann. This tutorial is based on his excellent post about mapping with Leaflet and GeoJSON, so check that out for a great primer if you’re new to mapping.

Setup

Before we can get into mapping, we’ll need a working Drupal 8 site. Savas Labs has previously gone over setting up a D8 site using Docker and creating a custom theme. That said, you don’t need to use Docker or a custom theme based on Classy to create your map - any Drupal 8 instance with a custom theme will do. In this tutorial, I’ll be referencing our custom theme called Mappy that we created for the Durham Civil Rights Mapping project.

Install contributed modules

First you’ll need to install several contributed modules in your site’s modules/contrib directory:

  • Geofield, which creates a new field type called geofield that we’ll use within a view
  • Views GeoJSON, a style plugin for Views that outputs data in GeoJSON, which can be used by Leaflet to create map points. Update: We’re using the 8.x-1.x-dev version of Views GeoJSON. You can follow the status of the module’s port to Drupal 8 here.

Update: We previously recommended installing the GeoPHP module, which was a dependency of the Geofield module. This dependency has been removed and the GeoPHP library must be managed with Composer.

# Install geophp library
# Run this in the Drupal root
composer require "phayes/geophp"

After running this command you should see the phayes/geophp directory in vendor. You can read more about installing dependencies via Composer on drupal.org.

There are 3 core modules you’ll need:

Rest and serialization are dependencies of Views GeoJSON, so they will be installed when Views GeoJSON is installed.

Add the Leaflet library

Screenshot of the Mappy theme showing Leaflet file locations

Head over to Leaflet’s website and download the latest stable release of the Leaflet library.

Move the Leaflet files into your custom theme directory (see mine for reference). You can put your files wherever you want to, you’ll just need to customize your filepaths in the libraries file in the next step.

You should also create a custom JavaScript file to hold your map code - ours is called map.js.

Next you’ll need to add the Leaflet library to your theme’s libraries file. In mappy.libraries.yml, shown below, I’ve defined a new library called leaflet and stated the paths to leaflet.css, leaflet.js and my custom JS file map.js.

Note that I’ve listed jQuery as a dependency - in Drupal 8 jQuery is no longer loaded on every page, so it needs to be explicitly included here.

# From mappy.libraries.yml
leaflet:
  css:
    theme:
      css/leaflet.css: {}
  js:
    js/leaflet.js: {}
    js/map.js: {}
  dependencies:
    - core/jquery

Once the library is defined, you need to include it on your page. This can be done globally by including the following in your [theme].info.yml file:

# In mappy.info.yml
libraries:
 - mappy/leaflet

You could also attach the library in a Twig template:


{# In some .html.twig file #}
{{ attach_library('mappy/leaflet') }}


For more methods of attaching assets to pages and elements, check out Drupal.org’s writeup on the matter.

Define a new content type

Now we need a content type that includes a location field.

  1. Navigate to admin/structure/types/add
  2. Give your new content type a name (we called ours “Place”), then click “Save and manage fields.”
  3. Add a new field with the field type Geofield. If Geofield isn’t an option, you should double-check that the Geofield module is installed. Add a label (we used “Location Coordinates”), then click “Save and continue.” Screenshot of geofield creation
  4. On the next page, leave the number of maximum values at 1 and click “Save field settings.”

That’s it! Obviously you can add more fields to your content type if you’d like, but all we need to generate a map marker is the geofield that we created.

Add some content

Next, add a few points by navigating to “node/add/place” (or node/add/whatever your content type is called) and create a few nodes representing different locations. A quick Google search can provide you with the latitude and longitude of any location you’d like to include.

Add a new view

Next we’ll add a view that will output a list of our “place” nodes as GeoJSON thanks to the Views GeoJSON plugin.

  1. Navigate to admin/structure/views/add
  2. Give your new view a name - ours is called “Points.”
  3. Under View Settings, show content of type “Place” (or whatever you named your new content type).
  4. Check the “Provide a REST export” box. Note that this box will only be available if the rest module is installed. Enter a path for your data to be output - we chose “/points”. Click “Save and edit.”
  5. Add the Location Coordinates field and choose GeoJSON as the output format. You can add other fields if you want to, but we’ll definitely need this one.
  6. Under “Format,” click on “Serializer.” Change the style to GeoJSON. When the GeoJSON settings pop up, add the following settings: Screenshot the rest export settings for the Places view
  7. Under “Pager,” change the number of fields to display to 0 (which means unlimited in this case).

For reference, here’s the settings for my Places view: Screenshot of settings for the Places view

We’ve just set up a view that outputs GeoJSON data at [site-url]/points. Take a minute to go to that URL and check out your data. In the next step, we’ll use this page to populate our map with points.

Create the map div and add a base map

The first thing we need to do is create a div with the id “map” in our template file. Our map is on the front page so I’ve inserted the following into page--front.html.twig. Place this code in the template your map will reside in. Feel free to customize the class, but the ID should remain “map.”

<div id="map" class="map--front"></div>

We also need to define a height and width of the map div. Ours is going to span the entire page background so I’ve included the following in my Sass file:

.map--front {
  // Set these to whatever you want.
  height: 100vh;
  width: 100%;
}

Previously we created a custom JavaScript file to hold our map code. Ours is called map.js and is located in our custom theme’s js directory. In the code below, we’ve added the map itself and set a center point and a zoom level. We’ve centered over our hometown of Durham, NC and selected a zoom level of 12 since all of our map markers are viewable within this region. Check out this explanation of zoom levels, or go for a little trial and error to get the right one for your map.

(function ($) {
  // Create map and set center and zoom.
  var map = L.map('map', { // The `L` stands for the Leaflet library.
    scrollWheelZoom: false,
    center: [35.9908385, -78.9005222],
    zoom: 12
  });
})(jQuery);

Now we need to add a base map. We’re using Positron by CartoDB. We’ll import the tiles and attribution, then add them as a layer to our map.

(function ($) {
  // Add basemap tiles and attribution.
  var baseLayer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
  });

  // Create map and set center and zoom.
  var map = L.map('map', {
    scrollWheelZoom: false,
    center: [35.9908385, -78.9005222],
    zoom: 12
  });

  // Add basemap to map.
  map.addLayer(baseLayer);
})(jQuery);

Go to your Drupal site and rebuild your cache and you should see your base map!

Screenshot the base map

Add our points

Next, we’re going to access the GeoJSON we’re outputting via our view to add points to our map. First, let’s add the path to our marker image.

L.Icon.Default.imagePath = '/themes/custom/mappy/images/leaflet/';

Now we’ll use .getJSON to retrieve our data from the url “/points,” then trigger the addDataToMap function to create a new layer containing our points via Leaflet’s geoJson function.

// Add points.
  function addDataToMap(data, map) {
    var dataLayer = L.geoJson(data);
    dataLayer.addTo(map);
  }

  $.getJSON('/points', function(data) {
    addDataToMap(data, map);
  });

Refresh - we’ve got points!

Screenshot of the map with markers

The last thing to do is add popups to each point when they’re clicked. We’ll insert this code in the addDataToMap function. If you actually navigate to [site-url]/points, you can inspect your GeoJSON and see which array keys have been assigned to the fields in your content type.

Screenshot of GeoJSON

I want to display the node title in the popup, which I can see is at feature.property.name.

 function addDataToMap(data, map) {
        var dataLayer = L.geoJson(data, {
            onEachFeature: function(feature, layer) {
                var popupText = feature.properties.name;
                layer.bindPopup(popupText);
            }
        });
        dataLayer.addTo(map);
    }

Now when I click on a point I get a nice little popup with the node title.

Screenshot of the map with a popup open

Check out the entire map.js file and be sure to visit Savas Labs GitHub repository for the Durham Civil Rights Mapping project and the completed site to see a Drupal 8 site in action!

May 15 2015
May 15

In this article, I am going to show you a clean way of using the Drupal 8 Ajax API without writing one line of JavaScript code. To this end, we will go back to the first custom form we built for Drupal 8 in a previous article and Ajaxify some of its behaviour to make it more user friendly.

Drupal 8 logo

An updated version of this form can be found in this repository under the name DemoForm (the demo module). The code we write in this article can also be found there but in a separate branch called ajax. I recommend you clone the repo and install the module in your development environment if you want to follow along.

DemoForm

Although poorly named, the DemoForm was very helpful in illustrating the basics of writing a custom form in Drupal 8. It handles validation, configuration and exemplifies the use of the Form API in general. Of course, it focuses on the basics and has nothing spectacular going on.

If you remember, or check the code, you’ll see that the form presents a single textfield responsible for collecting an email address to be saved as configuration. The form validation is in charge of making sure that the submitted email has a .com ending (a poor attempt at that but enough to illustrate the principle of form validation). So when a user submits the form, they are saving a new email address to the configuration and get a confirmation message printed to the screen.

In this article, we will move the email validation logic to an Ajax callback so that after the user has finished typing the email address, the validation gets automagically triggered and a message printed without submitting the form. Again, there is nothing spectacular about this behaviour and you will see it quite often in forms in the wild (typically to validate usernames). But it’s a good exercise for looking at Ajax in Drupal 8.

Ajax form

The first thing we need to do is move the email validation logic from the general validateForm() to a method that handles only this aspect:

/**
 * Validates that the email field is correct.
 */
protected function validateEmail(array &$form, FormStateInterface $form_state) {
  if (substr($form_state->getValue('email'), -4) !== '.com') {
    return FALSE;
  }
  return TRUE;
}

As you can notice, we’ve also changed the logic a bit to make sure the email address ends with a .com.

Then, we can defer to this logic from the main validation method to make sure our existing behaviour still works:

/**
 * {@inheritdoc}
 */
public function validateForm(array &$form, FormStateInterface $form_state) {
  // Validate email.
  if (!$this->validateEmail($form, $form_state)) {
    $form_state->setErrorByName('email', $this->t('This is not a .com email address.'));
  }
}

This way even if our form gets somehow submitted (programatically or otherwise), the validation will still be run.

Next, we need to turn to our form definition, specifically the email field, and make it trigger ajax requests based on a user interaction. This will be the act of a user changing the value of the field and removing focus from it:

$form['email'] = array(
  '#type' => 'email',
  '#title' => $this->t('Your .com email address.'),
  '#default_value' => $config->get('demo.email_address'),
  '#ajax' => [
    'callback' => array($this, 'validateEmailAjax'),
    'event' => 'change',
    'progress' => array(
      'type' => 'throbber',
      'message' => t('Verifying email...'),
    ),
  ],
  '#suffix' => '<span class="email-valid-message"></span>'
);

What we did new here is add the #ajax key to the array with some of the relevant keys. Additionally, we added a little markup after the form element as a wrapper for a short message regarding the validity of the email.

The callback inside the #ajax array points to a method inside our form class (validateEmailAjax()) while the event adds a javascript binding to this form element for the jQuery change event. Alternatively, you can also specify a path key instead of a callback, but in our case it would mean having to also set up a route and a controller which seems redundant. And we don’t want the wrapper key because we do not intend to fill up an area with returned content but want to fine grain the actions that result from the callback. For that, we will use Ajax commands.

To learn more about all of this, I encourage you to consult the Ajax API page or the Form API entry for Ajax. There are a handful of other options you can use to further customize the Ajax behavior of your form elements.

Now it’s time to write the callback method inside of our form class. This receives the $form array and $form_state object as arguments coming from the form that triggered the Ajax request:

/**
 * Ajax callback to validate the email field.
 */
public function validateEmailAjax(array &$form, FormStateInterface $form_state) {
  $valid = $this->validateEmail($form, $form_state);
  $response = new AjaxResponse();
  if ($valid) {
    $css = ['border' => '1px solid green'];
    $message = $this->t('Email ok.');
  }
  else {
    $css = ['border' => '1px solid red'];
    $message = $this->t('Email not valid.');
  }
  $response->addCommand(new CssCommand('#edit-email', $css));
  $response->addCommand(new HtmlCommand('.email-valid-message', $message));
  return $response;
}

Simply put, in this method, we perform the validation and return an Ajax response with multiple commands that differ depending on the validation result. With the CssCommand we apply some css directly to the email form element while with the HtmlCommand we replace the contents of the specified selector (remember the suffix from our form element?).

These commands pretty much map to jQuery functions so they are quite easy to grasp. You can find a list of all available commands on this page. And since we are using three new classes inside this method, we must remember to also use them at the top:

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\HtmlCommand;

And that is pretty much it. If you clear the cache and reload your form, typing into the email field and removing focus will trigger the callback to validate the email address. You’ll notice the little throbber icon there (which can be changed in the definition) and the short message we defined as well. A correct email address should highlight the field in green and print the OK message while on the contrary the color red is used with an opposite message.

If we had specified a wrapper in the form element definition, we could have returned some content (or render array) which would have been placed inside that selector. So you have the option of choosing between returning content or Ajax commands but I recommend the latter for most cases because they offer a more flexible (and consistent) behavior.

Conclusion

In this article we’ve seen an example of using Ajax to improve our form and make it more friendly to end users. And we have written exactly zero lines of javascript to accomplish this.

In our case, it really is a matter of preference or fancification. But if you are dealing with a 20 field form which has validation on multiple fields similar to this, using Ajax really makes sense. It doesn’t annoy users with having to submit the form only to realize their input is invalid.

Although forms are the main area where you’ll see Ajax in Drupal 8, there are a couple of other ways you can leverage it without writing JavaScript.

Once nice way is to add the use-ajax class on any link. This will have Drupal make an Ajax request to the URL in the href attribute whenever the link is clicked. From the callback you can return Ajax commands and perform various actions as needed. But do keep in mind that jQuery and other core scripts are not loaded on all pages for anonymous users (hence Ajax will gracefully degrade to regular link behaviour). So make sure you include these scripts for anonymous users if you need this behavior.

Dec 15 2014
Dec 15

Angular.js is the hot new thing right now for designing applications in the client. Well, it’s not so new anymore but is sure as hell still hot, especially now that it’s being used and backed by Google. It takes the idea of a JavaScript framework to a whole new level and provides a great basis for developing rich and dynamic apps that can run in the browser or as hybrid mobile apps.

logo_drupal

In this article I am going to show you a neat little way of using some of its magic within a Drupal 7 site. A simple piece of functionality but one that is enough to demonstrate how powerful Angular.js is and the potential use cases even within heavy server-side PHP frameworks such as Drupal. So what are we doing?

We are going to create a block that lists some node titles. Big whoop. However, these node titles are going to be loaded asynchronously using Angular.js and there will be a textfield above them to filter/search for nodes (also done asyncronously). As a bonus, we will also use a small open source Angular.js module that will allow us to view some of the node info in a dialog when we click on the titles.

So let’s get started. As usual, all the code we write in the tutorial can be found in this repository.

Ingredients

In order to mock this up, we will need the following:

  • A custom Drupal module
  • A Drupal hook_menu() implementation to create an endpoint for querying nodes
  • A Drupal theme function that uses a template file to render our markup
  • A custom Drupal block to call the theme function and place the markup where we want
  • A small Angular.js app
  • For the bonus part, the ngDialog Angular module

The module

Let us get started with creating a custom module called Ang. As usual, inside the modules/custom folder create an ang.info file:

name = Ang
description = Angular.js example on a Drupal 7 site.
core = 7.x

…and an ang.module file that will contain most of our Drupal related code. Inside this file (don’t forget the opening <?php tag), we can start with the hook_menu() implementation:

/**
 * Implements hook_menu().
 */
function ang_menu() {
  $items = array();

  $items['api/node'] = array(
    'access arguments' => array('access content'),
    'page callback'     => 'ang_node_api',
    'page arguments' => array(2),
    'delivery callback' => 'drupal_json_output'
  );

  return $items;
}
/**
 * API callback to return nodes in JSON format
 *
 * @param $param
 * @return array
 */
function ang_node_api($param) {

  // If passed param is node id
  if ($param && is_numeric($param)) {
    $node = node_load($param);
    return array(
      'nid' => $param,
      'uid' => $node->uid,
      'title' => check_plain($node->title),
      'body' => $node->body[LANGUAGE_NONE][0]['value'],
    );
  }
  // If passed param is text value
  elseif ($param && !is_numeric($param)) {
    $nodes = db_query("SELECT nid, uid, title FROM {node} n JOIN {field_data_body} b ON n.nid = b.entity_id WHERE n.title LIKE :pattern ORDER BY n.created DESC LIMIT 5", array(':pattern' => '%' . db_like($param) . '%'))->fetchAll();
    return $nodes;
  }
  // If there is no passed param
  else {
    $nodes = db_query("SELECT nid, uid, title FROM {node} n JOIN {field_data_body} b ON n.nid = b.entity_id ORDER BY n.created DESC LIMIT 10")->fetchAll();
    return $nodes;
  }
}

In hook_menu() we declare a path (api/node) which can be accessed by anyone with permissions to view content and which will return JSON output created in the callback function ang_node_api(). The latter gets passed one argument, that is whatever is found in the URL after the path we declared: api/node/[some-extra-param]. We need this argument because of we want to achieve 3 things with this endpoint:

  1. return a list of 10 most recent nodes
  2. return a node with a certain id (api/node/5 for example)
  3. return all the nodes which have the passed parameter in their title (api/node/chocolate for example, where chocolate is part of one or more node titles)

And this is what happens in the second function. The parameter is being checked against three cases:

  • If it exists and it’s numeric, we load the respective node and return an array with some basic info form that node (remember, this will be in JSON format)
  • If it exists but it is not numeric, we perform a database query and return all the nodes whose titles contain that value
  • In any other case (which essentially means the lack of a parameter), we query the db and return the latest 10 nodes (just as an example)

Obviously this callback can be further improved and consolidated (error handling, etc), but for demonstration purposes, it will work just fine. Let’s now create a theme that uses a template file and a custom block that will render it:

/**
 * Implements hook_theme().
 */
function ang_theme($existing, $type, $theme, $path) {
  return array(
    'angular_listing' => array(
      'template' => 'angular-listing',
      'variables' => array()
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function ang_block_info() {

  $blocks['angular_nodes'] = array(
    'info' => t('Node listing'),
  );

  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function ang_block_view($delta = '') {

  $block = array();

  switch ($delta) {
    case 'angular_nodes':
      $block['subject'] = t('Latest nodes');
      $block['content'] = array(
        '#theme' => 'angular_listing',
        '#attached' => array(
          'js' => array(
            'https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js',
            'https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-resource.js',
            drupal_get_path('module', 'ang') . '/lib/ngDialog/ngDialog.min.js',
            drupal_get_path('module', 'ang') . '/ang.js',
          ),
          'css' => array(
            drupal_get_path('module', 'ang') . '/lib/ngDialog/ngDialog.min.css',
            drupal_get_path('module', 'ang') . '/lib/ngDialog/ngDialog-theme-default.min.css',
          ),
        ),
      );
      break;
  }

  return $block;
}

/**
 * Implements template_preprocess_angular_listing().
 */
function ang_preprocess_angular_listing(&$vars) {
  // Can stay empty for now.
}

There are four simple functions here:

  1. Using hook_theme() we create our angular_listing theme that uses the angular-listing.tpl.php template file we will create soon.
  2. Inside the hook_block_info() we define our new block, the display of which is being controlled inside the next function.
  3. Using hook_block_view() we define the output of our block: a renderable array using the angular_listing theme and which has the respective javascript and css files attached. From the Google CDN we load the Angular.js library files, inside ang.js we will write our JavaScript logic and in the /lib/ngDialog folder we have the library for creating dialogs. It’s up to you to download the latter and place it in the module following the described structure. You can find the files either in the repository or on the library website.
  4. The last function is a template preprocessor for our template in order to make sure the variables are getting passed to it (even if we are actually not using any).

As you can see, this is standard boilerplate Drupal 7 code. Before enabling the module or trying out this code, let’s quickly create the template file so Drupal doesn’t error out. Inside a file called angular-listing.tpl.php, add the following:

        <div ng-app="nodeListing">
        
           <div ng-controller="ListController">
        
             <h3>Filter</h3>
             <input ng-model="search" ng-change="doSearch()">
        
              <ul>
                <li ng-repeat="node in nodes"><button ng-click="open(node.nid)">Open</button> {{ node.title }}</li>
              </ul>
        
             <script type="text/ng-template" id="loadedNodeTemplate">
             <h3>{{ loadedNode.title }}</h3>
             {{ loadedNode.body }}
             </script>
        
            </div>
        
        </div>

Here we have some simple HTML pimped up with Angular.js directives and expressions. Additionally, we have a <script> tag used by the ngDialog module as the template for the dialog. Before trying to explain this, let’s create also our ang.js file and add our javascript to it (since the two are so connected):

angular.module('nodeListing', ['ngResource', 'ngDialog'])

  // Factory for the ngResource service.
  .factory('Node', function($resource) {
    return $resource(Drupal.settings.basePath + 'api/node/:param', {}, {
      'search' : {method : 'GET', isArray : true}
    });
  })

  .controller('ListController', ['$scope', 'Node', 'ngDialog', function($scope, Node, ngDialog) {
    // Initial list of nodes.
    $scope.nodes = Node.query();

    // Callback for performing the search using a param from the textfield.
    $scope.doSearch = function() {
      $scope.nodes = Node.search({param: $scope.search});
    };

    // Callback to load the node info in the modal
    $scope.open = function(nid) {
      $scope.loadedNode = Node.get({param: nid});
      ngDialog.open({
        template: 'loadedNodeTemplate',
        scope: $scope
      });
    };

}]);

Alright. Now we have everything (make sure you also add the ngDialog files as requested in the #attached key of the renderable array we wrote above). You can enable the module and place the block somewhere prominent where you can see it. If all went well, you should get 10 node titles (if you have so many) and a search box above. Searching will make AJAX calls to the server to our endpoint and return other node titles. And clicking on them will open up a dialog with the node title and body on it. Sweet.

But let me explain what happens on the Angular.js side of things as well. First of all, we define an Angular.js app called nodeListing with the ngResource (the Angular.js service in charge communicating with the server) and ngDialog as its dependencies. This module is also declared in our template file as the main app, using the ng-app directive.

Inside this module, we create a factory for a new service called Node which returns a $resource. The latter is in fact a connection to our data on the server (the Drupal backend accessed through our endpoint). In addition to the default methods on it, we define another one called .search() that will make a GET request and return an array of results (we need a new one because the default .get() does not accept an array of results).

Below this factory, we define a controller called ListController (also declared in the template file using the ng-controller directive). This is our only controller and it’s scope will apply over all the template. There are a few things we do inside the controller:

  1. We load nodes from our resource using the query() method. We pass no parameters so we will get the latest 10 nodes on the site (if you remember our endpoint callback, the request will be made to /api/node). We attach the results to the scope in a variable called nodes. In our template, we loop through this array using the ng-repeat directive and list the node titles. Additionally, we create a button for each with an ng-click directive that triggers the callback open(node.nid) (more on this at point 3).
  2. Looking still at the template, above this listing, we have an input element whose value will be bound to the scope using the ng-model directive. But using the ng-change directive we call a function on the scope (doSearch()) every time a user types or removes something in that textfield. This function is defined inside the controller and is responsible for performing a search on our endpoint with the param the user has been typing in the textfield (the search variable). As the search is being performed, the results populate the template automatically.
  3. Lastly, for the the bonus part, we define the open() method which takes a node id as argument and requests the node from our endpoint. Pressing the button, this callback function opens the dialog that uses a template defined inside of the <script> tag with the id of loadedNodeTemplate and passes to it the current scope of the controller. And if we turn to the template file, we see that the dialog template simply outputs the title and the body of the node.

Conclusion

You can see for yourself the amount of code we wrote to accomplish this neat functionality. Most of it is actually boilerplate. A very fast node query block that delivers results asynchronously with all of its benefits. And if you know Angular.js, you can imagine the possibility of enhancing the Drupal experience further.

Now, are you interested to learn more about the love between Angular.js and Drupal? Would you have done anything differently? Let us know in the comments below!

Nov 10 2014
Nov 10

atrium-logo (1) The recent 2.23 version of Open Atrium contains a cool new interactive site builder and navigator application (see it in action). This application was written using the AngularJS framework.  The combination of Drupal, jQuery, and AngularJS proved to be powerful, but wasn’t without some pitfalls.

Using AngularJS in Drupal

AngularJS-large The basics of using Angular within Drupal is pretty straight-forward.  Simply reference the external AngularJS scripts using the drupal_add_js() function, then add your custom javascript app code, then use a tpl template to generate the markup including the normal Angular tags.  For example, here is the Drupal module code, javascript and template for a simple Angular app:

Drupal myapp.module code PHP // Implements hook_menu() function myapp_menu() { $items['myapp'] = array( 'page callback' => 'myapp_menu_callback', 'access callback' => TRUE, ); return $items; } // The menu callback to display the page function myapp_menu_callback() { drupal_add_js('https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js'); $base = drupal_get_path('module', 'myapp'); // data you want to pass to the app drupal_add_js(array( 'myapp' => array( 'title' => t('Hello World'), ), ), 'setting'); drupal_add_js($base . '/myapp.js'); drupal_add_css($base . '/myapp.css'); return theme('myapp', array()); } // Implements hook_theme(). function myapp_theme() { return array( 'myapp' => array( 'template' => 'myapp', ), ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 // Implements hook_menu()functionmyapp_menu(){  $items['myapp']=array(    'page callback'=>'myapp_menu_callback',    'access callback'=>TRUE,  );  return$items;}   // The menu callback to display the pagefunctionmyapp_menu_callback(){  drupal_add_js('https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js');     $base=drupal_get_path('module','myapp');     // data you want to pass to the app  drupal_add_js(array(    'myapp'=>array(      'title'=>t('Hello World'),    ),  ),'setting');     drupal_add_js($base.'/myapp.js');  drupal_add_css($base.'/myapp.css');     returntheme('myapp',array());}   // Implements hook_theme().functionmyapp_theme(){  returnarray(    'myapp'=>array(      'template'=>'myapp',    ),  );}
myapp.js script JavaScript (function ($) { var app = angular.module("myApp", []); app.controller("myAppController", function($scope) { $scope.settings = Drupal.settings.myapp; $scope.count = 1; $scope.updateCount = function(value) { $scope.count = $scope.count + value; } $scope.myClass = function() { return "myclass-" + $scope.count; } }) }(jQuery)); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (function($){  varapp=angular.module("myApp",[]);  app.controller("myAppController",function($scope){    $scope.settings=Drupal.settings.myapp;    $scope.count=1;       $scope.updateCount=function(value){      $scope.count=$scope.count+value;    }       $scope.myClass=function(){      return"myclass-"+$scope.count;    }  })}(jQuery));
myapp.tpl.php template

{{settings.title}}

Click to increment {{count}}

1 2 3 4 5 6 7 div class="myapp" ng-app="myApp" ng-controller="myAppController">  h3 ng-class="myClass()">{{settings.title}}/h3>  p>    a class="btn btn-default" ng-click="updateCount(1)">Click/a>      toincrement{{count}}  /p>/div>

Now, obviously we aren’t using the full Angular framework here.  We aren’t using any directives, nor are we really using Angular as a MVC framework.  But it gives you the idea of how easy it is to get started playing with basic Angular functionality.

Angular plus jQuery

Developing javascript applications in Angular requires a different mindset from normal Drupal and jQuery development.  In jQuery you are often manipulating the DOM directly, whereas Angular is a full framework that allows data to be bound and manipulated on page elements.  Trying to combine both is often a source of frustration unless you understand more about how Angular works behind the scenes. Specifically, Angular has it’s own execution loop causing a mix of Angular and jQuery code to not seem to execute in a straightforward order.  For example, in the above code, we set the class of the H3 based on the current “count” variable.  What if we modified the updateCount function to try and set a css property for this class:

JavaScript $scope.updateCount = function(value) { $scope.count = $scope.count + value; $('.' + $scope.myClass()).css('color', 'red'); } 1 2 3 4 $scope.updateCount=function(value){  $scope.count=$scope.count+value;  $('.'+$scope.myClass()).css('color','red');}

If you click the button you’ll notice that the css color does NOT change to red! The problem is that Angular is executing the query function call BEFORE it actually updates the page.  You need to delay the jQuery so it executes after the current Angular event loop is finished.  If you change the code to:

JavaScript $scope.updateCount = function(value) { $scope.count = $scope.count + value; setTimeout( function() { $('.' + $scope.myClass()).css('color', 'red'); }, 1); } 1 2 3 4 5 6 $scope.updateCount=function(value){  $scope.count=$scope.count+value;  setTimeout(function(){    $('.'+$scope.myClass()).css('color','red');  },1);}

then it will work.  The timeout value can be anything greater than zero.  It just needs to be something to take the jQuery execution outside the Angular loop. Now, that was a horrid example!  You would never actually manipulate the css and class properties like this in a real application.  But it was a simple way to demonstrate some of the possible pitfalls waiting to trap you when mixing jQuery with Angular.

Drupal Behaviors

When doing javascript the “Drupal way”, you typically create a behavior “attach” handler.  Drupal executes all of the behaviors when the page is updated, passing the context of what part of the page has changed.  For example, in an Ajax update, the DOM that was updated by Ajax is passed as the context to all attached behavior functions. Angular doesn’t know anything about these behaviors.  When Angular updates something on the page, the behaviors are never called.  If you need something updated from a Drupal behavior, you need to call Drupal.attachBehaviors() directly.

Angular with CTools modals

In the Open Atrium site map, we have buttons for adding a New Space or New Section.  These are links to the Open Atrium Wizard module which wraps the normal Drupal node/add form into a CTools modal popup and groups the fields into “steps” that can be shown within vertical tabs.  This is used to provide a simpler content creation wizard for new users who don’t need to see the full node/all form, and yet still allows all modules that hook into this form via form_alters to work as expected. The tricky part of this is that as you navigate through the sitemap, Angular is updating the URLs of these “New” links.  But CTools creates a Drupal Ajax object for each link with the “ctools-use-modal” class in it’s Drupal behavior javascript.  This causes the URL of the first link to be cached.  When Angular updates the page and changes the link URLs, this Ajax object cache is not updated. To solve this within the Open Atrium Sitemap app, an event is called when the page is updated, and we update the cached Ajax object directly via the Drupal.ajax array. This was a rather kludgy way to handle it.  Ultimately it would be better to create a true Angular “Directive” that encapsulates the CTools modal requirements in a way that is more reusable.

Summary

Angular can be a very useful framework for building highly interactive front-ends.  Using Drupal as the backend is relatively straight-forward.  Angular allowed us to create a very cool and intuitive interface for navigating and creating content quickly within Open Atrium far easier than it would have been in jQuery alone.  In fact, we began the interactive site map tool in jQuery and the code quickly became unmanageable.  Adding functionality such as drag/drop for rearranging your spaces and sections would have been a mess in jQuery.  In Angular it was very straight-forward. Once you understand how Angular works, you’ll be able to blend the best of Drupal + jQuery + Angular into very rich interfaces.  Programming in Angular is very different.  Learn more about Angular on the Phase2 blog!

Jan 08 2014
Jan 08

A client recently asked us for help with a very specific issue. The node edit page was hanging up, but only in Internet Explorer 10, and not in Firefox or Chrome. The client had WYSIWYG editor enabled.

This automatically pointed to a front end issue, not a server issue.

So, we investigated more, and found that the underlying issue is between Internet Explorer and JQuery with a large number of items to be parsed.

Internet Explorer was not able to parse the high number of token items listed (around 220). This causes the browse to hang when rendering the WYSIWYG page, with the following error message:

A script on this page is causing Internet Explorer to run slowly. If it continues to run, you computer might become responsive.

With the option to stop the script.

The real problem is with the critical issue described in #1334456, which is as yet not committed to the repository of the token module.

Fortunately there is an easy workaround, the steps are:

  • Install the Token Tweaks module.
  • Go to /admin/config/system/tokens.
  • Change the Maximum Depth limit from the default of 4 to 1
  • Save the changes.

Now the edit form for the node should work normally, and the browser, whichever it is, will not hang anymore.

Note: Thanks to Dave Reid for this workaround.

Nov 14 2013
Nov 14
Project: Global Zero
Responsive Iframes — yes it is possible

The Web has always had a love-hate relationship with 3rd-party content.  Whether that external content is self-contained functionality brought into a website via SaaS, or to add a donation form to your website in a way that reduces your PCI Requirements, or to possibly connect your disparate web properties together.  Back in the prehistoric days before responsive web development (a.k.a. two years ago) a common way to insert 3rd-party content was with an iframe. Something like:
<iframe src="http://example.com/widget" width="300" height="500" /></iframe>

The challenge with responsive design is the hard-coded width and height.  You might be able to choose reasonable settings for a desktop viewport, but a smaller mobile viewport may require something narrower and longer (or sometimes even wider and shorter).  And as the user interacts with the iframe (e.g. submits a form) the content may shrink and grow. Iframes quickly become untenable in a responsive world.  But often there is no alternative (Salsa, Blackbaud NetCommunity, Wufoo and many other CRM/donation/form platforms do not have adequate JavaScript APIs).

However there is a solution. We can use JavaScript to communicate between the iframe and the top-level page. With one slight problem — due to the same-origin policy an iframe at a different domain can't use JavaScript to directly communicate with the parent page.  Instead we have to use the postMessage() method to do cross-window messaging. This is a bit awkward, but there's good news at the end of this blog post.

postMessage()

Let's start with a quick tutorial on how postMessage() works. We'll set up a line of communication from the parent to the iframe and then send CSS and JavaScript links that can be used to style and otherwise manipulate the content.

// Parent
var iframe = document.getElementById('the-iframe');
var tags = '<script type="text/javascript" src="https://example.com/script.js"></script>';
tags += '<link type="text/css" rel="stylesheet" href="https://example.com/styles.css" />';
// Send a message to the iframe only if it contains content from
// https://frame.example.net.
iframe.contentWindow.postMessage(tags, 'https://frame.example.net');

Before we get too far there is one caveat: You must be able to have a small snippet of JavaScript in the iframe (e.g. If your donation form's configuration tool allows you to insert JavaScript). Unfortunately many 3rd-party tools don't allow this. Other JavaScript we can send over to the iframe via postMessage(), but we need to start with something.

// Iframe
function listener(event) {
  // Only listen to events from the top-level page.
  if (event.origin !== "http://example.com" &&
      event.origin !== "https://example.com" &&
      event.origin !== "http://dev.example.com" &&
      event.origin !== "https://dev.example.com"
  ) {
    return;
  }
  jQuery('head').append(event.data);
}
// We attach this differently for older versions of IE.
if (window.addEventListener) {
  addEventListener("message", listener, false);
}
else {
  attachEvent("onmessage", listener);
}

The cross-window messaging security model can be two-sided. The sender ensures that the data is only sent to trusted domains and the receiver checks that the message came from trusted domains.

Resizing the iframe

To resize the iframe we need to communicate in the other direction — the iframe needs to tell the parent how big it is.

// Iframe.
/**
* Send a message to the parent frame to resize this iframe.
*/
var resizeParentFrame = function() {
  var docHeight = jQuery('body').height();
  if (docHeight != parentDocHeight) {
    parentDocHeight = docHeight;
    // There is no need to filter this to specific domains, since the data is
    // not sensitive, so just send it everywhere.
    window.parent.postMessage(parentDocHeight, "*");
  }
};

// Check frequently to see if we need to resize again.
setInterval(resizeParentFrame, 250);

// Parent.
var listener = function (event, iframe) {
  // Ignore messages from other iframes or windows.
  if (event.origin !== 'https://frames.example.net') {
    return;
  }
  // If we get an integer, that is a request to resize the window
  var intRegex = /^\d+$/;
  if (intRegex.test(event.data)) {
    // Math.round() is important to make sure Internet Explorer
    // treats this as an integer rather than a string (especially
    // important if the code below were to add a value to the
    // event.data, although currently we aren't doing that).
    iframe.object.height(Math.round(event.data));
  }
}
// Setup the listener.
if (window.addEventListener) {
  addEventListener("message", listener, false);
}
else {
  attachEvent("onmessage", listener);
}

You can see these concepts in action on the Global Zero donate page. On a soon-to-be-launched project we're also taking it one step further to pass other information to/from the iframe.

If you do get this far, you'll note how this is a big pain in the arse; It will take several hours to get this all setup and QAed.  The good news is that at some point in the future we won't have to do this.  HTML5 has a new attribute for iframes called seamless. A seamless iframe will inherit the parent's CSS and adapt in size to fit the contents.  The bad news is that it has yet to be implemented by any browser, so it's still a long way off.

Photo by Bruce Denis


Thanks to Ben Vinegar for confirming that I'm not crazy to think this is the best way to do this.

Some browsers currently have very superficial support — they only remove the default iframe border. But that's just simple CSS that your browser-reset CSS is likely dealing with anyway.

May 14 2013
May 14

Jack, my co-themer here at Advomatic, and I will be doing a series of articles about how we use SASS and Compass on our projects. There are plenty of articles out there on what it is and how to get started, so we wanted to dig a little deeper, and share a few tips and ideas.

is that IE7 I smell?

Today I'll talk about Modernizr, which is a javascript library that will check to see if your browser supports HTML5 and CSS3 features. We use it on every project now to make sure we aren't serving unsupported stuff to browsers that can't handle it. One thing Modernizr does is add classes to your HTML tag, like "cssgradients" or "no-cssgradients," or "textshadow" or "no-textshadow" as the case may be. Combined with SASS, this can be a very simple way to limit your CSS3 work. Here's an example of how we now apply any of our css3 theming, using the way SASS allows you to check for parent classes, and the nice CSS3 includes of Compass.

h1.title {  // A double border, for browsers that support box shadows; single border for those that don't.
  border-bottom: 1px solid #c3c3bf;
  .boxshadow & {
    @include box-shadow($white 0 1px);
  }
}

Here's a slightly more elaborate example:

#footer {
  background-color #114163: // a baseline background color
  .lt-ie10 & { // dirty proprietary filter for IE9 and below
    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#2074b1', endColorstr='#114163');
  }
  .cssgradients & { // gradient for CSS3-supporting browsers
    @include background-image(linear-gradient(#2074b1, #114163));
  }
}

By the way, that handy ".lt-ie10" class on the html tag is standard now in Drupal's Zen base theme. It's very handy. While we try to avoid it, we also will add in classes for .mac, .pc, .chrome, .firefox and .safari, if we have some extremely browser-specific problems, which is rare. If you are curious, here's the javascript we use to add that information to the html tag.

Drupal.behaviors.targetBrowsersOS = {
  attach: function (context, settings) {
    // Check to see which operating system we're using.
    if (navigator.appVersion.indexOf("Mac")!=-1) {
      $('html').addClass('mac');
    }
    else {
      $('html').addClass('pc');
    }
    // Check to see if the browser is Safari and doublecheck that it is not Chrome.
    if (navigator.userAgent.indexOf('Chrome') > -1) {
      $('html').addClass('chrome');
    }
    if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
      $('html').addClass('safari');
    }
    if (navigator.userAgent.indexOf('Firefox') > -1) {
      $('html').addClass('firefox');
    }
    if (navigator.userAgent.indexOf('MSIE') > -1) {
      $('html').addClass('ie');
    }
  }
}

So, as you can imagine, this gives you the ability to customize what css various browsers are served, and leaner, cleaner experience all around. Stay tuned for more SASS/Compass tips and tricks!

Mar 26 2013
Mar 26

Episode Number: 

131

The Drupal 7 Floating Block module makes it easy to float a Drupal block along the sidebar as you scroll down the page. It uses a simple CSS selector to determine which blocks to float.

In this episode you will learn:

  • How to install and configure the Drupal 7 Floating Block module
  • How to determine the CSS selector to use for your block
  • How to get a Drupal block to float as you scroll down the page

Thanks to OSTraining for sponsoring this episode of the Daily Dose of Drupal.

DDoD Video: 

Feb 28 2013
Feb 28

Episode Number: 

117

The Drupal 7 jQuery SelectBox module is a simple module that makes HTML select boxes easier to style. It replaces the HTML form select element with easier to style HTML markup.

In this episode you will learn:

  • How to download and install the jQuery SelectBox module
  • What the jQuery SelectBox module is doing in the background to make the select boxes on the site continue to work correctly

Thanks to Drupalize.me for sponsoring this episode.

DDoD Video: 

Feb 21 2013
Feb 21

Episode Number: 

113

In the last two episodes, we covered building a basic Drupal 7 module that displayed a JavaScript confirmation before a user leaves a specific page. In this episode we continue where we left off and add the ability to display the JavaScript confirm form on specific content type node edit pages.

In this episode you will learn:

  • How to add a checkbox field on the administration form that displays all the content types on your Drupal site
  • How to verify you are on the node edit page of a specific content type

Thanks to Drupalize.me for sponsoring this episode.

DDoD Video: 

AttachmentSize 1.84 KB
Feb 20 2013
Feb 20

Episode Number: 

112

In this episode you will learn:

  • How to implement hook_menu to add an administrative page to your custom Drupal module
  • How to build a Drupal administrative form
  • How to match page patterns to determine when to display the Javascript confirmation box

Thanks to Drupalize.me for sponsoring this episode of the Daily Dose of Drupal.

DDoD Video: 

AttachmentSize 1.63 KB
Feb 19 2013
Feb 19

Episode Number: 

111

Learning module development in Drupal is not easy, but this Daily Dose of Drupal episode provides a very simple but practical module development video tutorial to use when learning about Drupal Module development. If you have a complex form on your Drupal websites, whether it is a Node creation form or perhaps even a webform, you may want to warn users before they navigate away from the page. This can help inform users that if they navigate away from the page before submitting the form, they may lose the contents of the form.

Note: In the uploaded module I added an extra feature that makes sure the confirmation form does not show up when submitting the form. I did not cover this in the video.

In this episode you will learn:

  • How to create a simple Drupal 7 module
  • How to create a Drupal 7 .info file
  • How to create a Drupal 7 .module file
  • How to use the Drupal 7 hook_init() function
  • How to use the drupal_add_js() function to add inline JavaScript
  • How to use the current_path() function to get the current Drupal system path

Thanks to Drupalize.me for sponsoring this episode.

DDoD Video: 

AttachmentSize 1.07 KB
Jan 31 2013
Jan 31

Replicating module_invoke_all and drupal_alter in Javascript

If you've ever written a Drupal module before you're likely familiar with Drupal's hook system. I'm not going to go in to details about how the hook system works, or why this particular pattern was chosen by Drupal's developers. What's important here is what this systems allows module developers to accomplish.

At its most basic, the hook system is what allows me to write a module that enhances or extends Drupal -- without ever having to modify a line of someone else's code. I can, for example, modify the list of blocks that are available on a given page by simply implementing a "hook" function in PHP that modifies the information that was already set up. This approach is one of the things that makes Drupal incredibly flexible!

When you're writing your own custom modules, it is customary to expose these types of hooks for other modules, too. That way, other developers can come along and make minor modifications or feature enhancements to your module by "piggybacking" on your module's functionality, rather than hacking your code. It also means that you don't have to anticipate every possible use case for your code: by providing these extension points, you allow future developers to extend it.

Drupal makes it really easy for modules developers to do this, and it provides a set of helper functions that allow you to easily broadcast these "I have a hook! Who wants to tie into it?" announcements to the world.

The case for APIs

Now, that's all well and good, but what if the functionality I want people to be able to alter or events I want people to be able to react to are encapsulated in Javascript? This is where Drupal breaks down a bit and we're left to our own devices. Drupal provides a simple mechanism for modules to essentially register a bit of code that they would like to be executed whenever Drupal.attachBehavoirs is called. This happens when the DOM is fully loaded and Drupal's Javascript code has been properly initialized, and anytime new elements have been added to the DOM via AJAX. And that's about it.

For most cases where Javascript needs to interact with Drupal this works just fine. What you're likely really after is some element in the DOM anyway so you can do your sweet web 2.0 fadeIn().

Sometimes, though, your Javascript needs are more complex than adding visual pizzaz. Consider this; You've been asked to write a module that integrates a video player from a third party site into Drupal. The video service offers a straightforward Javascript based embed option. All you have to do is include their Javascript file on the page and call the player.setup() method, passing in an embed code to the player so that it knows which video to play. Easy enough, and a common pattern.

Let's say the setup() method takes not only an embed code but also an array of additional paramaters to configure how the player appears and behaves. Some of those paramaters are callback functions -- the name of an additional Javascript function that should be called when certian things happen. Some examples of this might be 'onCreate' when the player is embeded and ready to start playback, 'onPause' when someone clicks the player's play/pause button, and so on. For our example we'll assume that we're implementing an 'onCreate' callback. It should be triggered by the video player after it's been embedded, and is ready for playback to start. (Another common example of something like this the jQuery.ajax, which can take 'success' and 'error' callbacks. Which one gets called depends on the result of the Ajax request.)

This should be simple, right? Just set the callback to 'Drupal.myModule.onCreate' and write the corresponding function in your mymodule.js file!

Except... Later on in the project, Kyle comes along and is told to implement an unrelated piece of functionality that also fade a DOM element in on the page after the video player has been embeded. Now two different functions both need to fire when the Video player has been created. You can't just pass in a second 'onCreate' callback function to the player.setup() method -- it only allows one value! So now Kyle is stuck trying to jam his unrelated Javascript in to your Drupal.myModule.onCreate function. Blam! You've got a mess of unrelated, hard to maintain code!

A better way of handling this would be for your module to re-broadcast the 'onCreate' callback to give other code a chance to respond to it as well. You could take it one step farther and implement a system that sends out a notification when the 'onCallback' event occurs, and subscribe to it with any functions that need it. That approach would be a lot like the module_invoke_all() function in Drupal's PHP API.

Lucky for you, there are all kinds of ways to do this in Javascript! I'll outline two of them below.

The Drupal Way

One way of solving the problem is to replicate the Drupal.behaviors system provided by core. That's actually pretty straightforward. You need to:

  • Create a well known place for someone to register their objects or functions.
  • Write a short snippet of Javascript that will loop through and execute these registered functions.
  • Call this Javascript at the appropriate time.
  • Ensure that your module's Javascript is loaded before that of other modules.

In your javascript code, you'll need to create a standard object that other modules can go to when they register their functions. In core, this is Drupal.behaviors. We'll create our own new object for this example.

var MyModule = MyModule || {};
MyModule.callbacks = {};

Then you'll need an easy way to call and execute any registered callbacks.

MyModule.executeCallbacks = function(data) {
   $.each(MyModule.callbacks, function(key, callback) {
       if ($.isFunction(callback)) {
          callback(data);
       }
   });
}

What this code does is loop over all the functions collected in MyModule.callbacks and executes them. Pretty simple, really! It works well for notifying any code of some "event" as long as you remember to call the MyModule.executeCallbacks() method at the appropriate times.

Now, any other module can register callback functions that will be called by the MyModule.executeCallbacks() method:

MyModule.callbacks.theirModuleOnCreate = function() {
   // Do some sweet Javascript stuff here ...
}

Put it all together by implementing your onCreate callback (the code we wanted to implement at the very beginning of this exercise!) and call the new code.

MyModule.onCreate = function() {
   // Give all modules that have registered a callback a chance to respond.
   MyModule.executeCallbacks();
}

Pretty painless. Just make sure your module's Javascript file is loaded before any others: in Drupal, you can do that by changing the weight of your module to -10, or something similar. If you don't do that, you'll end up with warnings about "MyModule.callbacks being undefined" when someone else's Javascript is loaded first, and tries to register a callback with your object.

This approach is easy to implement, but it still has some problems.

  • It's a major "Drupalism." For anyone familiar with Javascript but not with Drupal's way of doing things, it's a conceptual hurdle that needs to be overcome before understanding how to add a new behavior.
  • If one behavior fails, the execution stops: anything that hasn't be executed will not get called, and you're dependent on others to write code that doesn't fail.
  • There is no easy way to remove a behavior added by someone else's code, or to overwrite the way that Drupal core does something. Don't like the table drag javascript? The only way around it is Monkey Patching.

An alternative way

Another approach that's a bit more "Javascripty" is to use the jQuery.trigger() and jQuery.bind() methods. With them, you can create custom events that other modules can listen for and react too. It's a lot like using jQuery to intercept the 'click' event on a link, perform some custom action, then allowing the link to continue with it's processing. In this case, though, we'll be triggering our own custom event on a DOM element. To do this you need to:

  • Call jQuery.trigger on an object or DOM element in order to broadcast an event.
  • Use jQuery.bind on an object or DOM element to register a listener for an event.
  • Wash, rinse & repeat ...

As usual, the code samples below would go inside of your module's mymodule.js file and be included on the page when necessary via the drupal_add_js() PHP function.

Inside of our module's .onCreate callback, we use the jQuery.trigger() method to trigger our custom event and alert all listeners that they should go ahead and do their thing. It's not necessary to prefix our event names with 'myModule.' but it does lead to cleaner code. (It also makes it easier to unbind all of the events associated with a particular module in one step.) This approach is functionally equivalent to calling the MyModule.executeCallbacks() method from the previous example. We're telling anyone that wants to participate that now is the time to do it!

MyModule.onCreate = function() {
   // Trigger an event on the document object.
   $(document).trigger('myModule.onCreate');
}

The second piece of this puzzle is using the jQuery.bind() method to add an event listener that will be triggered any time our custom event is triggered. Each event listener receives the jQuery.Event object as the first argument. The code below is equivalent to the bit above where we register our callback with MyModule.callbacks.theirModule = {}

$(document).bind('myModule.onCreate', function(event) {
   // Do my fancy sliding effect here ...
});

Any number of modules can bind to the custom event, and respond to the onCreate callback event, without ever having to modify your module's Javascript.

Another technique that I've used in the past is to create a drupal_alter() style functionality in Javascript. This would allow others to modify the parameters that my code passes to a third party's API. It's easy to do, so since you can pass an array of additional arguments to the jQuery.trigger() method. They'll be passed along to any listeners added with jQuery.bind(). And, since complex data types in Javascript are inherently passed by reference, the listener can make changes to the incoming parameters and they'll be reflected upstream. Something like the following would do the trick.

MyModule.createWidget = function() {
  var parameters = {width: 250, height: 100, onCallback: 'MyModule.onCreate'};
  // Allow other modules to alter the parameters.
  $(document).trigger('myModule.alterParameters', [parameters]);
  superAwesomeWidgetAPI().setup(parameters);
}

Then anyone else could bind to the new 'myModule.alterParameters' event and receive the parameters object as an additional argument. The first argument for any function using jQuery.bind() to listen to an event is always the jQuery.event object.

$(document).bind('myModule.alterParameters', function(e, parameters) {
  // Here I can change parameters and it will be reflected in the function that triggered this event.
  parameters.width = 350;
});

While this method isn't perfect either, I like that it's closer to the Javascript programming patterns used in the broader world outside of Drupal. This means it's easier for someone not familiar with Drupal to understand my code and to quickly figure out how to work with it.

It does, however, still exhibit some of the same problems as the Drupal.behaviors method. Notably the fact that if any one listener has code that fails the whole system breaks down. In addition, you have to trigger and bind to events on either a DOM element or other Javascript object.

Summary.

Drupal itself doesn't come with a Javascript equivalent to the module_invoke_all() function, but there are a lot of ways that we can implement a similar system ourselves. When you run in to this problem in your development, I encourage you to use the second approach outlined: it has all the same capabilities of the Drupal.behaviors approach, with less code and a shallower learning curve.

These are by no means the only methods for accomplishing this sort of task in Javascript. Another for example would be the popular publish/suscribe pattern, but we'll wait to explore those in another article! Whichever approach you choose, it's important to build for future flexibility, just as you would with your PHP code.

Jan 25 2013
Jan 25

At January's meet-up of the Portland Drupal Users Group, I presented on using Backbone.js and Twig with Drupal (slides).

Backbone.js is a web application framework that runs entirely on the client—that is, inside of the web browser. It allows you to write a snazzy front-end for a web app that provides a RESTful web service.

Front-end framework... called Backbone?

It's called Backbone because it gives structure to your JavaScript user interface code. So that, y'know, it has a "back bone." Keeping with the metaphor, there's another framework, inspired by Backbone, called Spine.

Example Backbone App

This simple todo-list app doesn't use any backend; it persists data in the browser's LocalStorage. Have a look at its annotated source code, as it's a great, short-and-sweet example of Backbone in action.

Why Backbone and Twig?

Backbone.js is included in Drupal 8 core, powering the new in-place editing interface; Twig has been adopted to replace PHP templates and theme functions.

In Drupal 8, Twig templates are rendered on the server, as PHP templates are now. But with Twig templates not containing PHP or other code that needs to run on the server, we can use Twig today, in the browser, with any version of Drupal. Twig's PHP implementation could also be grafted onto an older Drupal, to be used just for your custom templates. But I haven't needed to do that, so it's left as an exercise for the reader. So far, I've just used Twig client-side, where it needs only be integrated directly with Backbone. I chose one of the many JavaScript ports of Twig available: twig.js from John Roepke.

Integrating Twig with Backbone

There are many ways to accomplish using Twig templates instead of underscore.js templates (Backbone's default templating system). Here's a very simple method:

<script type="text/html" id="template-welcome">
  <h1 id="{{ html_id }}">{{ 'Welcome' | t }}<h1>
  {% if error_message %}
    <p class="error">{{ error_message }}</p>
  {% endif %}
</script>
var WelcomeView = Backbone.View.extend({
  template: twig({ data: $("#template-welcome").html() }),
  render: function() {
    var markup = this.template.render({
      html_id: "page-title",
      error_message: Drupal.t("DANGER!")
    });
    this.$el.html(markup);
    return this;
  }
});

This example shows a template that is shoe-horned into—err, I mean stored in—a <script> tag in your HTML. The raw content within the <script> tag is retrieved using jQuery and passed to the global twig() function, which compiles the template. When the view is rendered, we pass in any variables the template needs, like you do when calling theme() in Drupal. Unlike Drupal, there's no pre-template preprocess callback in this example, so the method invoking the template is solely responsible for what data goes into it. After rendering the template into a string of markup, we replace the view's HTML with that markup.

More in the Slides

This has been a brief introduction to Backbone and Twig. More information and links are in my slides, including an example of creating a JSON endpoint in Drupal that Backbone can query to retrieve model or collection data.

Jan 21 2013
Jan 21

Old telegraph map

Internationalization, or “i18n” for short (because there are 18 characters between the “i” and the “n” in that lengthy word), is the process of designing a web application so that it can be adapted to various languages and world regions. CivicActions has had an opportunity to work on some localization projects using Drupal and i18n in recent years. We've learned a lot and want to share some of our tips about using Javascript for string translation.

1. Loading up our JavaScript in a way that strings will be translatable:

The most flexible way to do this is with drupal_add_js()1.  You don’t want to manually add script tags to the page template, or you could find that your JavaScript strings will not be translatable with Drupal.t() -- see section below.

Use your template.php to load the JavaScript files if you want any kind of conditionality. For example you might want to load just some files onto just some pages. This way you can limit what you load to what you need.

In Drupal 6:

function saladtheme_preprocess_page(&$vars, $hook) {


$current_url = drupal_get_path_alias($_GET["q"]);

$theme_path = drupal_get_path('theme', 'saladtheme');


    if (strpos($current_url, ‘articles/tomatosalad’)) {

       drupal_add_js($theme_path .”/js/lettuce.js”, "theme");

    }


}

And in Drupal 7:

function saladtheme_preprocess_html(&$variables, $hook) {

 $current_url = drupal_get_path_alias($_GET["q"]);
 $theme_path = drupal_get_path('theme', 'saladtheme');

  if (strpos($current_url, ‘articles/tomatosalad’)) {


      drupal_add_js($theme_path .”/js/lettuce.js”);


  }


}

Consider the order in which you load the JS files, as the files loaded first will appear first in the HTML head section2.

2. Drupal.t()

Now that we have our JS files loaded up correctly, we might might want to translate some of the strings that they contain. 

If you add Drupal’s t() function to a php page, you can have the text translated into multiple languages, with each new text entry stored in the database, via a call to locale(); if the string has already been translated, then the translated version is returned.

In the case of Drupal.t(), from misc/drupal.js: Drupal.t() does not add the strings to the DB.  What it does do is replace, on the page, any previously translated strings, which can be found in the JavaScript object (Drupal.locale.strings), in a Drupal generated file (in the files directory, under directory languages, with the name of the current language).

But how does the JavaScript located string get inserted in the DB in the first place?  Well, it begins with drupal_add_js().  Each time a JS file is added with drupal_add_js(), its filepath is added to a static array called $javascript.  When drupal_get_js() builds up the JavaScript HTML output, it also calls locale_update_js_files(), which loads the complete $javascript array by an empty call to drupal_add_js(NULL, NULL, NULL).  _locale_parse_js_file() parses each of the files in the filepaths stored in $javascript and adds the new translatable strings to the DB, much like locale() does when t() calls it.

As with t(), we can use replacement values in Drupal.t().  This page shows a clear example.

On the other hand, one noticeable difference between t() and Drupal.t() is that Drupal.t() does not insert the run time value of variables into the database, which is something you can do with t().   We might add t($dynamic_variable); we can use variables when necessary, but it’s something to avoid in the case of user specified content (as Gábor Hojtsy points out here).  My hunch is that  php variables don’t work with Drupal.t(), and locale_parse_js_file(), because the file is parsed as plain text.  There are work-arounds, however, such as using nodes to store the translations, and thus avoiding the use of Drupal.t().

We hope this helps you to get a better handle on using translatable strings in JavaScript.  We’re always learning more and would be curious to hear from others using Javascript for string translation.


Footnotes:
1. If the JS file is loaded on every page, you can just use: scripts[] = js/script.js, in your mytheme.info
2. Drupal 7 allows you to set the weight in drupal_add_js(), which could come in useful if JS files, are getting loaded from other locations, such as modules.

Nov 23 2012
Nov 23

Drupal 7 Ajax Framework Example

For a Daily Dose of Drupal episode that covers this blog post topic as well, take a look at Drupal 7 Ajax Framework Link Example.

After struggling to find documentation on how to take advantage of the Drupal Ajax Framework with just a simple HTML link I decided to provide an example to anyone else who might be struggling with the same problem. The documentation on drupal.org is very detailed, however most of the documentation centers around using the Drupal 7 Ajax Framework with forms. In this case I just want to use the Drupal 7 Ajax Framework with a simple link.

I am going to start by creating a simple module that will provide an example. First we create the ajax_link.info file:


name = "Ajax Link Test"
description = "A simple Ajax link example"
core = 7.x

The next step is to create the ajax_link.module file. In this module file we start with the hook_menu implementation. We will first just create the hook_menu implementation for a very simple page.

/**
 * Implements hook_menu().
 */
function ajax_link_menu() {
  $items = array();
 
  $items['ajax-test'] = array(
    'title' => 'Ajax Test',
    'type' => MENU_NORMAL_ITEM,
    'page callback' => 'ajax_link_page',
    'access arguments' => array('access content'),
  );
 
  return $items;
}

Next we create the page callback for our hook_menu implementation. This page just displays a simple link that will load additional HTML to the page using Ajax when clicked.

/**
 * Callback function that displays a simple Ajax powered link.
 */
function ajax_link_page() {
  return array(
    '#type' => 'link',
    '#title' => t('Ajax Link'),
    '#href' => 'my-ajax-test/nojs',
    '#prefix' => '<div id="ajax-link">',
    '#suffix' => '</div><div id="ajax-display"></div>',
    '#ajax' => array(
      'effect' => 'fade',
    ),
  );
}

Now we save everything, clear the cache and take a look at the page.

Drupal 7 Ajax Framework test page

It is not working yet, we need to create the hook_menu item for the Ajax callback. Our hook_menu implementation now looks like:

/**
 * Implements hook_menu().
 */
function ajax_link_menu() {
  $items = array();
 
  $items['ajax-test'] = array(
    'title' => 'Ajax Test',
    'type' => MENU_NORMAL_ITEM,
    'page callback' => 'ajax_link_page',
    'access arguments' => array('access content'),
  );
 
  $items['my-ajax-test/%'] = array(
    'title' => 'Ajax test callback',
    'type' => MENU_CALLBACK,
    'page callback' => 'ajax_link_callback',
    'page arguments' => array(1),
    'access arguments' => array('access content'),
  );
 
  return $items;
}

We now create the Ajax callback. We build this out to handle both Ajax calls and requests with no Javascript. The Ajax framework will replace the "nojs" part of the path with "ajax" when the link is clicked.

/**
 * Ajax callback to display the current time.
 */
function ajax_link_callback($ajax) {
  // Do any database queries, processing, etc.
  $time = t('The current time is: !time', array('!time' => date('Y-m-d H:i:s')));
 
  if ($ajax == 'ajax') {
    $commands = array();
    // Ajax command to replace the #ajax-display element with the current time.
    $commands[] = ajax_command_replace('#ajax-display', "<div id='ajax-display'>" . $time . "</div>");
    // Add a visual "changed" marker to the '#ajax-display' element.
    $commands[] = ajax_command_changed('#ajax-display');
    // Menu 'page callback' and #ajax['callback'] functions are supposed to
    // return render arrays. If returning an Ajax commands array, it must be
    // encapsulated in a render array structure.
    ajax_deliver(array('#type' => 'ajax', '#commands' => $commands));
  }
  else {
    // No ajax, just display the time on a page using renderable array.
    return array(
      '#markup' => $time,
    );
  }
}

We now have everything we need for a simple example. The comments in the code examples should help explain what is going on. Lets look at a screenshot of what it looks like after the link is clicked.

Drupal 7 Ajax Framework response

The last step was one that took me awhile to figure out. What if you want to execute or trigger some extra JavaScript/Jquery after the Ajax call is complete. Perhaps you need to manipulate other things on the page, or need to modify the html that was just loaded through the Drupal 7 Ajax Framework. In this case the easiest way I found is to build a simple Jquery plugin and call that plugin using the ajax_command_invoke function.

The first step is to create the JavaScript file, we will call it ajax_link.js. In this example I simply hide the Ajax link, set a timeout to remove the loaded content after 5 seconds, and then re-display the Ajax link. You could of course do anything you needed to in the JavaScript file. Below is my jQuery plugin.

(function($) {
  $.fn.ajax_link = function() {
    $('#ajax-link').hide();
    setTimeout(function() {
      $('#ajax-display').fadeOut().html("").show();
      $('#ajax-link').fadeIn();
    }, 5000)
  }
})(jQuery);

We need to modify the info file to make sure this Javascript file is added on every page.


name = "Ajax Test"
description = "A simple Ajax link example"
core = 7.x
scripts[] = ajax_link.js

The last step is to add the ajax_command_invoke function call to our Ajax callback in our module file.

/**
 * Ajax callback to display the current time.
 */
function ajax_link_callback($ajax) {
  // Do any database queries, processing, etc.
  $time = t('The current time is: !time', array('!time' => date('Y-m-d H:i:s')));
 
  if ($ajax == 'ajax') {
    $commands = array();
    // Ajax command to replace the #ajax-display element with the current time.
    $commands[] = ajax_command_replace('#ajax-display', "<div id='ajax-display'>" . $time . "</div>");
    // Add a visual "changed" marker to the '#ajax-display' element.
    $commands[] = ajax_command_changed('#ajax-display');
    // Trigger our ajax_link jQuery plugin.
    $commands[] = ajax_command_invoke(NULL, "ajax_link");
 
    // Menu 'page callback' and #ajax['callback'] functions are supposed to
    // return render arrays. If returning an Ajax commands array, it must be
    // encapsulated in a render array structure.
    ajax_deliver(array('#type' => 'ajax', '#commands' => $commands));
  }
  else {
    // No ajax, just display the time on a page using renderable array.
    return array(
      '#markup' => $time,
    );
  }

That is it. You can now test out a working example of loading content through the Drupal 7 Ajax Framework using a link. After the link loads the Ajax content, you trigger additional JavaScript to be run on the page. Simple as that!

Let me know if you have other ways of doing something like this in the comments below.

Sep 28 2012
Sep 28

One year ago I listened to Allen Wirfs-Brock of the Mozilla Foundation deliver the closing keynote for StrangeLoop 2011. Wirfs-Brock's central claim was jarring. Keep in mind, this is a conference whose attendee list is dominated by language designers, database architects, PhDs, and people whose credentials make the term "senior" seem like a gaping understatement. Yet in front of this crowd, Wirfs-Brock unabashedly coronated JavaScript the new king of programming languages.

I did not buy it. But a year later, I'm changing my mind.

I like JavaScript. It was, in all honesty, the first language I felt really comfortable in. I learned with the web. I started programming in 1995, at age 16. My summer internship led me into C, Java, Perl, and JavaScript all at once. JavaScript was my favorite, doubtless because its bindings to the browser made results more gratifying. "Look, ma! I put a message in the status bar!"

But as I matured as a programmer, I looked back on those heady experiments as pretend-programming with a toy language. JavaScript had a firm place in my constellation of programming languages: It was for tricking out web pages.

A decade and a half later, I found myself at StrangeLoop hearing an otherwise credible source claim that JavaScript is the new C. Really? You can imagine my skepticism.

Since hearing Wirfs-Brock a year ago, several things changed for me. First, within weeks of StrangeLoop 2011, I begin writing Node.js code. Second, I read some of the technical papers from Google on the V8 engine (start here), and then read some of the ECMA proposals for the next version of JavaScript. Finally, I wrote an application framework for Node.js -- always a great opportunity to stretch one's grasp of a language and an environment.

I know it's the same language that I used to pop up alert dialogs in my pimply high-school years, but it feels different now. Did it grow up, or did I?

On September 25, StrangeLoop 2012 concluded. And who should deliver the closing keynote? None other than Brendan Eich, the father of JavaScript.

Eich is disarming, funny, and intensely intelligent. Quick to point out the work of others, he portrays the JavaScript community as a vibrant group of intelligent individuals who, differences aside, have the best interests of the language users in mind. His presentation began with a humorous history of the mistakes of JavaScript, then moved to upcoming features and standards work, and concluded with a look at some of the more exciting JavaScript projects.

It didn't come across as a sales pitch; it came across as an acceptance speech, an oath of office. "I hereby solemnly swear that JavaScript will do right by you."

And by far, the most interesting aspect of this presentation was Eich's promotion of JavaScript as the new replacement for the VM. Here is the text of one of Eich's slides:

JavaScript > bytecode

  • Dynamic typing = no verification
  • Type inference = delayed optimization
  • Would byte code compress as well?
  • Bytecode standardization would suck
  • Bytecode versioning would suck more
  • Low-level byte code is future-hostile
  • Many humans like writing JavaScript

Oh yes he did! CoffeeScript, ClojureScript, Dart… Eich enthusiastically champions building languages that compile (or transcode) to JavaScript. (Did you know there's a project to rebuild the JVM in JavaScript? The Doppio project also spoke at StrangeLoop 2012.)

On the server; on the desktop; on mobile devices -- JavaScript already is pervasive. And if you've convinced a theater full of language lawyers, scientists, CTOs, and architects that JavaScript is the new C, you've won. Wirfs-Brock and Eich won.

Hail to the king, baby.

Sep 10 2012
Sep 10

You may have run into a situation in Drupal 7 in which you only need to apply a JavaScript behavior one time. In most cases your JavaScript seems to be executing fine, however you might notice that sometimes things seem to be executing two times or more. This may be getting triggered by some type of AJAX call that causes your JavaScript behaviors to get executed again. In this post we will examine how we can prevent these duplicate behaviors from being applied by using a very simple example.

Simple Duplicate JavaScript Behavior Example

First we will look at a small piece of HTML. This is just a simple h3 element with a div. The goal is to have the div expand when the h3 element is clicked (there are many reasons why this is not the best approach for achieving this functionality, but this will be suitable for a simple example).

<h3 class="slider-trigger">Slider Trigger</h3>
<div class="slider">This is my slider text. This text will automatically expand when the Slider Trigger is clicked</div>

Now we add our JavaScript:

(function ($) {
  Drupal.behaviors.myCustomJS = {
    attach: function(context, settings) {
 
      $('h3.slider-trigger').click(function(){
        $('.slider').slideToggle();
      });
    }
  };
})(jQuery);

Now in most cases this would work great. However, if you have something that makes an AJAX call and the JavaScript behaviors get applied again. Then you may end up with a situation in which clicking the Slider Trigger h3 element, will cause the slider text to open and close, thus duplicating the sliding behavior. This is obviously an issue, luckily Drupal 7 makes it easy to fix.

Solution: Using Jquery Once

Drupal 7 integrates the Jquery Once plugin into Drupal 7 core. This plugin adds a simple class to the HTML element to ensure that the behavior is only processed one time. Here is how we would modify our JavaScript to work with the Jquery Once plugin.

(function ($) {
  Drupal.behaviors.myCustomJS = {
    attach: function(context, settings) {
      $('h3.slider-trigger').once('myslider', function() {
        $('h3.slider-trigger').click(function(){
          $('.slider').slideToggle();
        });
      });
    }
  };
})(jQuery);

This JavaScript will now add a myslider-processed class to the h3 slider-trigger element to ensure the Jquery Click handler is only added one time.

Do you have any other examples of when this has been useful? If so, leave them in the comments below.

Aug 22 2012
Aug 22

Not only do we build big websites at Four Kitchens, but we also migrate them. We’ve seen all kinds of migrations and have had to overcome different kinds of challenges to deal with them. In a previous blog installment, my colleague Mark Theunissen discussed Migrating Old HTML Files Into Drupal. In this post he touted the wonderful QueryPath library and what it enables you to do for HTML migrations. I too am a fan of QueryPath, but my biggest complaint is that it’s not quite jQuery.

Most seasoned web developers will know a good deal of jQuery and be comfortable with its callbacks and the way it behaves. Its selectors and return values are known factors and are things web developers have embraced over the years. QueryPath gets close, but due to PHP’s and more specifically Drupal’s procedural programming flow you often find yourself doing a dance to deal with data from QueryPath that would otherwise be simple to access in jQuery.

Thankfully there’s a JavaScript solution to this problem: jsdom. jsdom is an implementation of the DOM completely in JavaScript for use with node.js applications. That’s cool and all, but what does that really give you? Well, you can load any arbitrary JavaScript files along with an HTML file in jsdom, and in our specific use case this means jQuery.

Got your attention yet? Good, let’s look at an example. Let’s say you had N HTML documents like this:

<div class=”header”>Foo</div>
<div class=”content”>
Hoodie non sem mustache pellentesque eros specs tellus sagittis 
8-bit ut molestie cred malesuada tellus viral leo. Porta 8-bit eu 
ultricies vegan urna sit vinyl bibendum pharetra bicycle sagittis 
malesuada artisan risus gravida fixie. Pellentesque eget San 
Francisco lorem ut bahn mi quam ultricies Brooklyn morbi ipsum 
DIY bibendum ligula keytar sed tempus VHS. Lorem vivamus 
indie sapien lorem brunch cursus leo cred gravida congue keytar 
non risus VHS in odio Austin eu.
</div>

Using jsdom you could cut up the documents with jQuery and prepare them for a Drupal migration import based solely on database queries. Observe:

var jsdom = require('jsdom');
var files = [ 'path/to/file1', 'path/to/file2' ];
files.forEach(function(file) {
  jsdom.env(
    file,
    [ 'http://code.jquery.com/jquery-1.8.0.min.js' ],
    function (errors, window) {
      if (errors) {
        // Bail, yo!
        // An intelligent developer would throw an error here.
        return;
      }
 
      (function($) {
        // Get the content.
        var title = $('.title').html();
        var body = $('.content').html();
 
        // Prep the values.
        var values = {
          guid: file,
          title: title,
          body: body
        };
 
        // Write to a migration DB that's shared with Drupal.
        abstractedDatabaseWrite(values);
      }(window.jQuery));
    }
  );
});

Now that you’ve loaded up your migration table with content from the source files your Drupal migration code only needs to query a database to create content.

If you’re not quite sold yet, consider the case where your only migration source list is an HTML file with a menu. If you don’t use jsdom you’d need to extract the contents of that menu and put them into a source map that would be read into a database table that would then be used by migration classes to parse individual files with QueryPath (yuck). Alternatively, you could use jsdom to parse the menu, open each individual file, and create database records for the content you need to migrate.

Oh, and did I mention that it’s fast? jsdom + jQuery isn’t nearly as fast as native DOM implementations with jQuery, but in our tests it’s been faster than QueryPath and the code is generally easier to follow for people that are familiar with jQuery. I can see it now, the back-end development team convinces the front-end guys to write a script for them to cut up all the content that they need to migrate… With an offering of beer, of course. Prost!

Jul 09 2012
Jul 09

Even though we have six weeks until DrupalCon Munich, I’ve already started scouring the schedule for interesting frontend talks. As you might know, one of my favorite topics is mobile web development and there’s plenty of interesting stuff this time around.

Sessions

Having worked alongside Sam “Snugug” Richard on the drupal.org D7 upgrade efforts, I’m very excited to see his talk on Responsive Design with Sass+Compass. Not limited to Drupal, Sam is an active contributor to the Sass community, producing a number of awesome tools that make constructing responsive layouts a snap. This one is a must-see!

Ken Woodworth, one of the creators of the beautiful (and responsive) DrupalCon Denver site, has a session on designing and implementing flexible interfaces. Responsive interfaces are a lot more than a few lines of CSS, and insight into the responsive design process is !important.

Angie “webchick” Byron will be giving a state of the union on Drupal 8. While it’s not specifically about RWD, Drupal 8 will be responsive out of the box. Best to get the scoop now.

Core conversations

For those not content with the general update from webchick, there are a number of Core Conversations that go in depth, covering the various efforts for core Drupal 8 development. And yes, several of these deal with making the next Drupal responsive.

John Albin, Drupal 8 mobile initiative lead, will give an update on the direction of D8’s responsive core themes, the mobile admin UX, and frontend performance. We will be sprinting the final day of sessions and possibly the day after. If you want to get involved, stop by #drupal-mobile on irc.freenode.net and say hi.

Join the discussion around Spark, Acquia’s distribution created to explore new authoring experiences designed from the ground up with responsive websites in mind.

Though it isn’t specifically about RWD, I couldn’t help but mention Théodore “nod_” Biadala’s discussion around the effort he is spearheading for better JavaScript in Drupal core. This talk will reveal how much more appealing Drupal 8 is going to be for frontend developers. Better tools FTW!

Training

Last but not least, if you’re interested in hands-on training during DrupalCon Munich, Four Kitchens is offering a full-day responsive web design training August 20th, the day before sessions start. Visit our training page for a full topic listing. Space is limited, so register before it sells out!

Jun 20 2012
Jun 20

Pronto.js is designed to be a high performance asynchronous application framework that makes it simple to chain together components to build sophisticated application logic. It's the JS equivalent of the PHP Fortissimo framework.

One characteristic that makes both Pronto.js and Fortissimo stand apart is that they provide an alternative to the MVC pattern. They use the Chain-of-Command pattern, which takes a route name and maps it to a series of "commands", each of which is responsible for a different part of the processing. Well-written commands become highly reusable, which makes application development rapid and yet still reliable.

When you build an application the components get chained together into routes with code like this (Pronto.js):

register.route('search')
      .does(InitializeSearchService, 'initialization')
      .does(QueryRemoteSearchService, 'do-search')
        .uses('query').from('get:q')
      .does(SearchTheme, 'format-search-results')
        .uses('searchResults').from('cxt:do-search')
    ;

(Fortissimo code looks similar: $register->route('search')->does(/*…*/)) The simple example above registers the route search to a series of commands that each perform part of the overall task of running a search and formatting the response.

Commands (IntiailizeSearchService, QueryRemoteSearchService and so on) are short pieces of object-oriented code (prototypes in JS, classes in PHP) that take predefined input, perform a simple task, and then return data. My typical command is around 20 lines of code.

I know this is just a brief teaser. We're working on several cool applications built on these technologies. With Pronto.js, we've been able to integrate with a wide variety of NPM packages, while Fortissimo and the Symfony (and other) PHP libraries can be easily combined. In the future, I'll blog some more about Fortissimo and Pronto.js.

Pages

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web