Building the Bing apps for Windows 8

Overview

For Windows 8, the Bing team built News, Weather, Finance, Sports, Travel and Maps apps. This technical overview provides insight on the architecture of these apps, key Windows 8 features and the contracts they use, common controls they employ, and world readiness more generally.

Several members of the Bing team formed an apps team approximately one year ago to deliver a set of apps powered by Bing for Windows 8. The focus of these apps is to keep users informed by delivering fast and fluid experiences, with content from multiple sources. All the apps are optimized for touch and tablet devices, but also work great with a keyboard and mouse. We have spent the last several months making these apps world-ready.

When developing the apps, we had two objectives: to build a set of great apps to make Windows 8 even more compelling and to serve as a model for app developers. With this post, we provide you with a technical overview of the apps and offer insight/resources you can use to develop your own apps. Through the process, we learned a lot – even a few things we’d do differently next time. Keep reading for the full story.

Find the weather conditions for your places of interest.

Weather app: Find the weather conditions for your places of interest.

Architecture overview

Platform services

All our apps are written in HTML/Java Script, except the Maps app, which is built in XAML/C#. All the apps share a common client platform that provides several essential services, such as instrumentation, caching, query services, settings, roaming, profile management, market customizations, and speech fundamentals. We deliberately chose to have client side caching, to invest in prefetching and for the client to set the time to live of various pieces of data for a couple reasons.

Our apps are designed for all PC devices, many of which we expect to be tablet devices. Windows 8 tablets can be used to consume content as well as create content by consumers and businesses alike. In many situations, we know users go through various states of connectivity (fully connected on fast networks, weak connectivity over WiFi or cellular, flaky networks, and even no connectivity). Our goal was to build a rich client app that’s different from a webpage. We used IE concepts of caching all network data to the file system and re-using cached data while waiting for fresh data to arrive. We also designed experiences for when cached data wasn’t available and network requests failed. For these scenarios, we, provide graceful error messages, retry mechanisms and listen for network connectivity changes from the OS to automatically trigger a retry.

Query services

Our apps use several services that are built on the Bing stack and/or in Windows Azure. The Bing services and data are served via dedicated application servers built on the Bing platform. For example, the Finance app heavily uses data and services from Azure, whereas data and services for the Maps app are provided via the Maps control, which is built by the Bing Maps team. Our apps also have other articles, images and videos that are hosted in our Content Management System. If you want to create apps that take advantage of the Bing web index or industry leading publisher data, check out the Windows Azure Marketplace, where you can access the Bing Search API and info from leading publishers like STATS Sports or agencies like the United Nations.

Caching

Supporting hundreds of millions of users interacting with rich apps that are powered by lots of data and content requires a lot of server computing. To scale the hardware needs along with the number of users, we have invested heavily in caching at different tiers. Our content management system rendering server, services in Azure, as well as the local client platform itself cache data to reduce the server load. If you’re anticipating several thousand users, consider local caching as a means to limit server computing and to improve the user experience – you can find out more about app caching (AppCache) on the Dev Center.

Some of the ways our apps make use of caching on the client involve:

  1. Managing low and high res versions of the same image – choosing what to display based on what’s in the cache or not.
  2. Client-side caching that override server-set content ages. Oftentimes the services we use aren’t owned by us and we can’t control those lifetimes, in which case our client decides on the caching.
  3. Being careful to at least display stale cached data instead of downloading new data that may be invalid.

Custom controls

Design is a fundamental differentiator for our apps and plays a key role in building visually organized and intuitive to use apps. To achieve a consistent look and feel and a visually immersive experience across our apps, we built custom controls on top of the compelling UI controls that Windows provides. If you want a consistent look and feel across your apps or want to deliver against a signature user interface, we encourage you to take advantage of the flexibility of Windows and build your own UX framework or custom controls on top of Windows 8. There are ample resources available on MSDN to help you create your own UX framework and custom controls.

Failsafe

If your app relies upon data from a 3rd party, plan on full outages as well as partial outages from your data providers from time to time. We strive to make our apps avoid single points of failure and we build in several failsafe mechanisms. We invested in various failsafe practices on both the server and client side primarily for the benefit of our users. Across all our apps, we have data and services from many parts of Microsoft as well as industry partners. All these external sources have varying degrees of uptime SLAs and TTM (time to mitigate) service level outages. Any given panorama on any application could rely on data and services from multiple sources. To provide a good end user experience, we use failsafe techniques both on the server and client side, including caching, backup providers, graceful degradation of features or falling back on acceptably stale data in some cases (for example, destination information). Think about these failsafe measures and take steps to create adaptive UI and error messaging when design and develop your app, not during or after a data failure.

Client framework – language choices

One question developers frequently ask is why we implement using client-side HTML, rather than server-based HTML5. The short answer is that apps on Windows 8 are not websites. Creating a great Windows Store app requires a deep level of integration with the platform that we simply cannot achieve with standard web code. If we had delivered features purely via the same HTML5 normally viewed in the browser, the pages would not have had access to the features of Windows 8 that really make the user experience great.

Building an app gave us several advantages, including:

  1. Using the built-in controls of the Windows JavaScript Library (WinJS), which allowed us to leverage the power of Windows 8 and build on top of the experiences that the Windows team has built. We think we’ve delivered a great user experience (UX) provided by WinJS.
  2. Native app platform features not accessible via HTML5 in a browser:
    • Device features such as access to the microphone, webcam, or network
    • Shared file locations such as My Documents, Music, Pictures or Videos
    • Participate in contracts, including those for searching, sharing, settings, contacts etc.
    • In addition certain libraries are better in WinRT compared to HTML5. For example, the WinRT geolocation APIs are richer than those found in HTML5.
  3. Supplementing the JavaScript code with performant, statically-typed, code in C#. We used language constructs that don’t exist in JavaScript – for example, LINQ as well as the .Net4.5 Asynchronous framework. The latter is very important because it helps ensure correctness in asynchronous operations, which can get quite complex.     
    Be aware that if you write a WinMD to host business logic (whether in C# or C++), there’s a cost to marshaling lots of data between languages. It’s better to have one call that marshals a lot of data, rather than many calls that marshal little data.  Additionally, C# and JavaScript have separate, independent garbage collectors. Because they’re not in sync, it’s possible that your memory usage will be larger than if you were to write an app wholly using JavaScript or C#.      
    When we developed our apps we decided that the benefits of a JavaScript and C# mixed language app were worth the extra costs of working around these complexities. We made sure that our apps still performed great. If you’re considering combining JavaScript and C# in your app, keep the extra cost and complexity in mind. This way you can choose the architecture that best fits the requirements of your app.
  4. Building our Maps application on top of XAML to access the native DirectX Map control. This approach gave us even more control and greater performance of our rendering (critical with a map!).

Developing for Windows offers a standard set of experiences (screen size, touch targets, view states, orientation dimensions, among others). We wanted to tailor our code to offer the best user experience, given the user’s device. A one size fits all HTML5 experience doesn’t let us deliver a consistent and optimized user experience.

 

By: Ray Yagubyan

 

$1,649.00

 

 

Ray Yagubyan

Click on image for details.

Pros

  • Super thin and handsome looking
  • Excellent performance for an Ultrabook

Cons

  • Relatively short battery life

Manufacturer’s Description

Radically thin, supremely strong, scratch  resistant and easy to clean: White Gorilla Glass 2 makes the beauty of the 13.3″  Aspire S7 Series gleam at an ultra-thin 11.9 mm. The 11.6″ model, with its sleek  aluminum unibody, is just 12.2 mm slim. Either Ultrabook gives you the freedom  to go anywhere, carefree and looking fabulous.

Performance

Overall Performance
Worldbench Score 72
Worldbench Version 8
Battery
Battery Life 3:54  (hh:mm)
Start Up
Start Up 11  seconds (lower is better)
Office Productivity
PCMark 7 Productivity Suite 2506  score (higher is better)
Web Browsing
Peacekeeper 2356  score (higher is better)
Storage Performance
File Compression 124  seconds (lower is better)
PCMark 7 Storage Test 5373  score (higher is better)
Power Usage
Idle power usage 10.5  Watts
Content Creation
Image Editing 240  seconds (lower is better)
Audio Encoding 260  seconds (lower is better)
Video Encoding 188  seconds (lower is better)
Gaming
Dirt Showdown, High Quality, 1920×1080 13.8  Frames per second (higher is better)
3DMark 11, 1920×1080 Extreme 222  score (higher is better)
Civilization V, Leader Benchmark, Low Quality,  1366×768 642  Frames per second (higher is better)
Civilization V, Leader Benchmark, High Quality,  1920×1080 10.3  Frames per second (higher is better)
Civilization V, Late Game View, Ultra Quality,  1920×1080 5  Frames per second (higher is better)
Dirt Showdown, Low Quality, 1366×768 35  Frames per second (higher is better)
Civilization V, Late Game View, Low Quality, 1366×768 11.4  Frames per second (higher is better)
Civilization V, Leader Benchmark, Ultra Quality,  1920×1080 8.1  Frames per second (higher is better)
Civilization V, Late Game View, High Quality,  1920×1080 6  Frames per second (higher is better)
3DMark 11, 1280×720 Performance 661  score (higher is  better)

Acer isn’t  kidding when they describe the $1699, S7-391 ultraportable as cutting edge. This  Windows  8 laptop is so thin (11.9 mm) and stiff, it could double as a weapon in the  wrong hands. Did I say wrong hands? Assuming you can afford it, there are no  wrong hands for this laptop. It’s forward thinking in its design, eye-catchingly  attractive, travels light, and is a heck of a performer.

The S7 is a  touchscreen laptop, which partly explains the extreme rigidity–you’re can’t get  away with users poking at a display that’s not sturdily constructed or flexes  too much. The white Gorilla Glass 2 outer panels and an anodized aluminum  keyboard deck that are in play also give the S7 a modern look that’s vaguely  Mac-like. The keyboard is short-throw yet types nicely, and the one-piece  touchpad is very responsive, perhaps overly so for my ham-handed use. The  touchpad’s placement is spot on and it’s also press-to-click so you can turn off  tapping if you’d like.

 

Features and performance

Component-wise, our S7-391-9413 (a Canadian SKU  identical to the US S7-391-9886) test unit boasted a state-of-the-art selection:  a Core i7-3517U CPU, 4GB (the max) of DDR3 memory, and twin  integrated 128GB SSDs striped in RAID 0 for 256GB of total disk capacity. These  lifted the laptop to an impressive 72 score on our new WorldBench 8 test suite.  That compares well with the Lenovo  IdeaPad Yoga, which posted a WorldBench 8 score of 60, although the Yoga  PCWorld reviewed used a mobile Core i5 CPU and costs $600 less.

The S7-391  utilizes Intel’s integrated HD 4000 graphics which in most cases delivers  playable games rates up to 1366 by 768 resolution; some games will require  stepping down further in resolution. DiRT Showdown posted 35 frames per second  at 1366 by 768 low detail levels, and eked out 11.4fps in the demanding  Civilization V late game test at low detail and 1366 by 768.

Our unit booted  in a mere 11 seconds–not the fastest we’ve seen, but still quick. Less  expensive S7 models with slower CPUs and smaller hard drives are available from  $1199. Unfortunately there’s no 8GB memory option which would be nice for power  users running virtual machines and the like.

 

Display and connectivity

The S7-391′s display packs a 1920 by 1080 grid  of pixels into a mere 13.3 diagonal inches. That makes for a super-fine and  basically unnoticeable dot pitch, but also means many users will need to adjust  the text and icon settings to 125% of normal in order to read them. That action  means the same amount of usable screen real estate as with a lower resolution  display, but much smoother text and wonderful video. The display pivots on its  hinges 180 degrees so the entire laptop will lay flat against a table. However,  with so much keyboard deck between you and the display, this seems useful only  when you’re standing over the unit. Rotating a full 360 degrees might work  better.

The port selection on the S7-391 is as good as you’ll find on an  ultraportable. There are two USB 3.0 ports, a micro-HDMI port, a  headset/headphone jack, as well as an SD/MMC memory card slot. Unlike some  vendors, Acer realizes that you’ll probably need or want to use Ethernet on  occasion and thoughtfully includes a USB to Ethernet adapter. There’s an HDMI to  VGA adapter as well, but you’ll have to grab your own micro-HDMI to HDMI cable  if you’ve the need. Connectivity is top-notch with 802.11 a/b/g/n Wi-Fi,  Bluetooth 4.0, and the aforementioned tk Ethernet USB adapter.

 

Ultra-thin at a cost

The S7-391 travels at a mere 3.5 pounds with AC  adapter, and an ounce or two heavier with the two USB adapters. The laptop  itself is a mere 2.8 pounds. Battery life might be a concern for some at only 3  hours and 54 minutes, but for a laptop this thin and light with high-performance  components, you’re not going to do much better.

All in all, the S7-391 is a  nice laptop to use and show off. It would be nice to have an 8GB option and  better battery life, but neither is essential for the vast majority of users.  The design and overall usability are top notch. And it’s an eye-catching system,  sure to draw attention whenever you pull it out.

 

Thanks

Ray Yagubyan


10 C++ 11 Features Every C++ Developer Should Use

This article discusses a series of features new to C++11 that all developers should learn and use. There are lots of new additions to the language and the standard library, and this article barely scratches the surface. However, I believe some of these new features should become routine for all C++ developers. You could probably find many similar articles evangelizing different C++11 features. This is my attempt to assemble a list of C++ features that should be a norm nowadays.

Table of contents:

auto

Before C++11 the auto keyword was used for storage duration specification. In the new standard its purpose was changed towards type inference. auto is now a sort of placeholder for a type, telling the compiler it has to deduce the actual type of a variable that is being declared from its initializer. It can be used when declaring variables in different scopes such as namespaces, blocks or initialization statement of for loops.

Collapse | Copy Code

auto i = 42;        // i is an int
auto l = 42LL;      // l is an long long
auto p = new foo(); // p is a foo*

Using auto usually means less code (unless your type is int which is one letter shorter). Think of iterators in STL that you always had to write while iterating over containers. It makes obsolete creating typedefs just for the sake of simplicity.

Collapse | Copy Code

std::map<std::string, std::vector<int>> map;
for(auto it = begin(map); it != end(map); ++it) 
{
}

You should note that auto cannot be used as the return type of a function. However, you can use auto in place of the return type of function, but in this case the function must have a trailing return type. In this case auto does not tell the compiler it has to infer the type, it only instructs it to look for the return type at the end of the function. In the example below the return type of function compose is the return type of operator+ that sums values of types T1 and T2.

Collapse | Copy Code

template <typename T1, typename T2>
auto compose(T1 t1, T2 t2) -> decltype(t1 + t2)
{
   return t1+t2;
}
auto v = compose(2, 3.14); // v's type is double

nullptr

Zero used to be the value of null pointers, and that has drawbacks due to the implicit conversion to integral types. The keyword nullptr denotes a value of type std::nullptr_t that represents the null pointer literal. Implicit conversions exists from nullptr to null pointer value of any pointer type and any pointer-to-member types, but also to bool (as false). But no implicit conversion to integral types exist.

Collapse | Copy Code

void foo(int* p) {}

void bar(std::shared_ptr<int> p) {}

int* p1 = NULL;
int* p2 = nullptr;   
if(p1 == p2)
{
}

foo(nullptr);
bar(nullptr);

bool f = nullptr;
int i = nullptr; // error: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type

For backward compatibility 0 is still a valid null pointer value.

Range-based for loops

C++11 augmented the for statement to support the “foreach” paradigm of iterating over collections. In the new form, it is possible to iterate over C-like arrays, initializer lists and anything for which the non-member begin() and end() functions are overloaded.

This for each for is useful when you just want to get and do something with the elements of a collection/array and don’t care about indexes, iterators or number of elements.

Collapse | Copy Code

std::map<std::string, std::vector<int>> map;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
map["one"] = v;

for(const auto& kvp : map) 
{
  std::cout << kvp.first << std::endl;

  for(auto v : kvp.second)
  {
     std::cout << v << std::endl;
  }
}

int arr[] = {1,2,3,4,5};
for(int& e : arr) 
{
  e = e*e;
}

Override and final

I always founded the virtual methods badly designed in C++ because there wasn’t (and still isn’t) a mandatory mechanism to mark virtual methods as overridden in derived classes. The virtual keyword is optional and that makes reading code a bit harder, because you may have to look through the top of the hierarchy to check if the method is virtual.  I have always used, and encouraged people to use the virtual keyword on derived classes also, to make the code easier to read. However, there are subtle errors that can still arise. Take for instance the following example:

Collapse | Copy Code

class B 
{
public:
   virtual void f(short) {std::cout << "B::f" << std::endl;}
};

class D : public B
{
public:
   virtual void f(int) {std::cout << "D::f" << std::endl;}
};

D::f is supposed to override B::f. However, the signature differ, one takes a short, one takes an int, therefor B::f is just another method with the same name (and overload) and not an override. You may call f() through a pointer to B and expect to print D::f, but it’s printing B::f.

Here is another subtle error: the parameters are the same, but the method in the base class is marked const, while me method in the derived is not.

Collapse | Copy Code

class B 
{
public:
   virtual void f(int) const {std::cout << "B::f " << std::endl;}
};

class D : public B
{
public:
   virtual void f(int) {std::cout << "D::f" << std::endl;}
};

Again, these two are overloads and not overrides, so if you call f() through a pointer to B it will print B::f and not D::f.

Fortunately there is now a way to describe your intentions. Two new special identifiers (not keywords) have been added: override, to indicate that a method is supposed to be an override of a virtual method in a base class, and final, to indicate that a derived class shall not override a virtual method.  The first example would become:

Collapse | Copy Code

class B 
{
public:
   virtual void f(short) {std::cout << "B::f" << std::endl;}
};

class D : public B
{
public:
   virtual void f(int) override {std::cout << "D::f" << std::endl;}
};

This now triggers a compiler error (the same error you’d get for the second example too, if using the override specifier):

‘D::f’ : method with override specifier ‘override’ did not override any base class methods

On the other hand if you intend to make a method impossible to override any more (down the hierarchy) mark it as final. That can be in the base class, or any derived class. If it’s in a derived classes you can use both the override and final specifiers.

Collapse | Copy Code

class B 
{
public:
   virtual void f(int) {std::cout << "B::f" << std::endl;}
};

class D : public B
{
public:
   virtual void f(int) override final {std::cout << "D::f" << std::endl;}
};

class F : public D
{
public:
   virtual void f(int) override {std::cout << "F::f" << std::endl;}
};

function declared as ‘final’ cannot be overridden by ‘F::f’

Strongly-typed enums

“Traditional” enums in C++ have some drawbacks: they export their enumerators in the surrounding scope (which can lead to name collisions, if two different enums in the same have scope define enumerators with the same name), they are implicitly converted to integral types and cannot have a user-specified underlying type.

These issues have been fixed in C++ 11 with the introduction of a new category of enums, called strongly-typed enums. They are specified with the enum class keywords. They no longer export their enumerators in the surrounding scope, are no longer implicitly converted to integral types and can have a user-specified underlying type (a feature also added for traditional enums).

Collapse | Copy Code

enum class Options {None, One, All};
Options o = Options::All;

Smart pointers

There have been tons of articles written on this subject, therefore I just want to mention the smart pointers with reference counting and auto releasing of owned memory that are available:

  • unique_ptr: should be used when ownership of a memory resource does not have to be shared (it doesn’t have a copy constructor), but it can be transferred to another unique_ptr (move constructor exists).
  • shared_ptr: should be used when ownership of a memory resource should be shared (hence the name).
  • weak_ptr: holds a reference to an object managed by a shared_ptr, but does not contribute to the reference count; it is used to break dependency cycles (think of a tree where the parent holds an owning reference (shared_ptr) to its children, but the children also must hold a reference to the parent; if this second reference was also an owning one, a cycle would be created and no object would ever be released).

On the other hand the auto_ptr is obsolete and should no longer be used.

When you should unique_ptr and when you should use shared_ptr depends on the ownership requirements and I recommend reading this discussion.

The first example below shows unique_ptr. If you want to transfer ownership of an object to another unique_ptr use std::move (I’ll discuss this function in the last paragraph). After the ownership transfer, the smart pointer that ceded the ownership becomes null and get() returns nullptr.

Collapse | Copy Code

void foo(int* p)
{
   std::cout << *p << std::endl;
}
std::unique_ptr<int> p1(new int(42));
std::unique_ptr<int> p2 = std::move(p1); // transfer ownership

if(p1)
  foo(p1.get());

(*p2)++;

if(p2)
  foo(p2.get());

The second example shows shared_ptr. Usage is similar, though the semantics are different since ownership is shared.

Collapse | Copy Code

void foo(int* p)
{
}
void bar(std::shared_ptr<int> p)
{
   ++(*p);
}
std::shared_ptr<int> p1(new int(42));
std::shared_ptr<int> p2 = p1;

bar(p1);   
foo(p2.get());

The first declaration is equivalent to this one

Collapse | Copy Code

auto p3 = std::make_shared<int>(42);

make_shared<T> is a non-member function and has the advantage of allocating memory for the shared object and the smart pointer with a single allocation, as opposed to the explicit construction of a shared_ptr via the contructor, that requires at least two allocations. In addition to possible overhead, there can be situations where memory leaks can occur because of that. In the next example memory leaks could occur if seed() throws an error.

Collapse | Copy Code

void foo(std::shared_ptr<int> p, int init)
{
   *p = init;
}
foo(std::shared_ptr<int>(new int(42)), seed());

No such problem exists if using make_shared.  The third sample shows usage of weak_ptr. Notice that you always must get a shared_ptr to the referred object by calling lock(), in order to access the object.

Collapse | Copy Code

auto p = std::make_shared<int>(42);
std::weak_ptr<int> wp = p;

{
  auto sp = wp.lock();
  std::cout << *sp << std::endl;
}

p.reset();

if(wp.expired())
  std::cout << "expired" << std::endl;

If you try to lock on an expired weak_ptr (the object is weakly reference has been released) you get an empty shared_ptr.

Lambdas

Anonymous functions, called lambda, have been added to C++ and quickly rose to prominence. It is a powerful feature borrowed from functional programming, that in turned enabled other features or powered libraries.  You can use lambdas wherever a function object or a functor or a std::function is expected.  You can read about the syntax here.

Collapse | Copy Code

std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);

std::for_each(std::begin(v), std::end(v), [](int n) {std::cout << n << std::endl;});

auto is_odd = [](int n) {return n%2==1;};
auto pos = std::find_if(std::begin(v), std::end(v), is_odd);
if(pos != std::end(v))
  std::cout << *pos << std::endl;

A bit trickier are recursive lambdas. Imagine a lambda that represents a Fibonacci function. If you attempt to write it using auto you get compilation error:

Collapse | Copy Code

auto fib = [&fib](int n) {return n < 2 ? 1 : fib(n-1) + fib(n-2);};

Collapse | Copy Code

error C3533: 'auto &': a parameter cannot have a type that contains 'auto'
error C3531: 'fib': a symbol whose type contains 'auto' must have an initializer
error C3536: 'fib': cannot be used before it is initialized
error C2064: term does not evaluate to a function taking 1 arguments

The problem is auto means the type of the object is inferred from its initializer, yet the initializer contains a reference to it, therefore needs to know its type. This is a cyclic problem. The key is to break this dependency cycle and explicitly specify the function’s type using std::function.

Collapse | Copy Code

std::function<int(int)> lfib = [&lfib](int n) {return n < 2 ? 1 : lfib(n-1) + lfib(n-2);};

non-member begin() and end()

You probably noticed I have used in the samples above non-member begin() and end() functions. These are a new addition to the standard library, promoting uniformity, consistency and enabling more generic programming. They work with all STL containers, but more than that they are overloadable, so they can be extended to work with any type. Overloads for C-like arrays are also provided.

Let’s take for instance the previous example where I was printing a vector and then looking for its first odd element. If the std::vector was instead a C-like array, the code might have looked like this:

Collapse | Copy Code

int arr[] = {1,2,3};
std::for_each(&arr[0], &arr[0]+sizeof(arr)/sizeof(arr[0]), [](int n) {std::cout << n << std::endl;});

auto is_odd = [](int n) {return n%2==1;};
auto begin = &arr[0];
auto end = &arr[0]+sizeof(arr)/sizeof(arr[0]);
auto pos = std::find_if(begin, end, is_odd);
if(pos != end)
  std::cout << *pos << std::endl;

With non-member begin() and end() it could be put as this:

Collapse | Copy Code

int arr[] = {1,2,3};
std::for_each(std::begin(arr), std::end(arr), [](int n) {std::cout << n << std::endl;});

auto is_odd = [](int n) {return n%2==1;};
auto pos = std::find_if(std::begin(arr), std::end(arr), is_odd);
if(pos != std::end(arr))
  std::cout << *pos << std::endl;

This is basically identical code to the std::vector version. That means we can write a single generic method for all types supported by begin() and end().

Collapse | Copy Code

template <typename Iterator>
void bar(Iterator begin, Iterator end) 
{
   std::for_each(begin, end, [](int n) {std::cout << n << std::endl;});

   auto is_odd = [](int n) {return n%2==1;};
   auto pos = std::find_if(begin, end, is_odd);
   if(pos != end)
      std::cout << *pos << std::endl;
}

template <typename C>
void foo(C c)
{
   bar(std::begin(c), std::end(c));
}

template <typename T, size_t N>
void foo(T(&arr)[N])
{
   bar(std::begin(arr), std::end(arr));
}

int arr[] = {1,2,3};
foo(arr);

std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
foo(v);

static_assert and type traits

static_assert performs an assertion check at compile-time. If the assertion is true, nothing happens. If the assertion is false, the compiler displays the specified error message.

Collapse | Copy Code

template <typename T, size_t Size>
class Vector
{
   static_assert(Size < 3, "Size is too small");
   T _points[Size];
};

int main()
{
   Vector<int, 16> a1;
   Vector<double, 2> a2;
   return 0;
}

Collapse | Copy Code

error C2338: Size is too small
see reference to class template instantiation 'Vector<T,Size>' being compiled
   with
   [
      T=double,
      Size=2
   ]

static_assert becomes more useful when used together with type traits. These are a series of classes that provide information about types at compile time. They are available in the <type_traits> header. There are several categories of classes in this header: helper classes, for creating compile-time constants, type traits classes, to get type information at compile time, and type transformation classes, for getting new types by applying transformation on existing types.

In the following example function add is supposed to work only with integral types.

Collapse | Copy Code

template <typename T1, typename T2>
auto add(T1 t1, T2 t2) -> decltype(t1 + t2)
{
   return t1 + t2;
}

However, there are no compiler errors if one writes

Collapse | Copy Code

std::cout << add(1, 3.14) << std::endl;
std::cout << add("one", 2) << std::endl;

The program actually prints 4.14 and “e”. But if we add some compile-time asserts, both these lines would generate compiler errors.

Collapse | Copy Code

template <typename T1, typename T2>
auto add(T1 t1, T2 t2) -> decltype(t1 + t2)
{
   static_assert(std::is_integral<T1>::value, "Type T1 must be integral");
   static_assert(std::is_integral<T2>::value, "Type T2 must be integral");

   return t1 + t2;
}

Collapse | Copy Code

error C2338: Type T2 must be integral
see reference to function template instantiation 'T2 add<int,double>(T1,T2)' being compiled
   with
   [
      T2=double,
      T1=int
   ]
error C2338: Type T1 must be integral
see reference to function template instantiation 'T1 add<const char*,int>(T1,T2)' being compiled
   with
   [
      T1=const char *,
      T2=int
   ]

Move semantics

This is yet another important and well covered topic from C++11, that one could write a series of articles, not just a paragraph. Therefore I will not get into too many details, but encourage you to find additional readings, if you’re not already familiar with the topic.

C++11 has introduced the concept of rvalue references (specified with &&) to differentiate a reference to an lvalue or an rvalue. An lvalue is an object that has a name, while an rvalue is an object that does not have a name (a temporary object). The move semantics allow modifying rvalues (previously considered immutable and indistinguishable from const T& types).

A C++ class/struct used to have some implicit member functions: default constructor (only if another constructor is not explicitly defined) and copy constructor, a destructor and a copy assignment operator. The copy constructor and the copy assignment operator perform a bit-wise (or shallow) copy, i.e. copying the variables bitwise. That means if you have a class that contains pointers to some objects, they just copy the value of the pointers and not the objects they point to. This might be OK in some cases, but for many cases you actually want a deep-copy, meaning that you want to copy the objects pointers refer to, and not the values of the pointers. In this case you have to explicitly write copy constructor and copy assignment operator to perform a deep-copy.

What if the object you initialize or copy from is an rvalue (a temporary). You still have to copy its value, but soon after the rvalue goes away. That means an overhead of operations, including allocations and memory copying that after all, should not be necessary.

Enter the move constructor and move assignment operator. These two special functions take a T&& argument, which is an rvalue. Knowing that fact, they can modify the object, such as “stealing” the objects their pointers refer to. For instance, a container implementation (such as a vector or a queue) may have a pointer to an array of elements. When an object is instantiating from a temporary, instead of allocating another array, copying the values from the temporary, and then deleting the memory from the temporary when that is destroyed, we just copy the value of the pointer that refers to the allocated array, thus saving an allocation, copying a sequence of elements, and a later de-allocation.

The following example shows a dummy buffer implementation. The buffer is identified by a name (just for the sake of showing a point revealed below), has a pointer (wrapper in an std::unique_ptr) to an array of elements of type T and variable that tells the size of the array.

Collapse | Copy Code

template <typename T>
class Buffer 
{
   std::string          _name;
   size_t               _size;
   std::unique_ptr<T[]> _buffer;

public:
   // default constructor
   Buffer():
      _size(16),
      _buffer(new T[16])
   {}

   // constructor
   Buffer(const std::string& name, size_t size):
      _name(name),
      _size(size),
      _buffer(new T[size])
   {}

   // copy constructor
   Buffer(const Buffer& copy):
      _name(copy._name),
      _size(copy._size),
      _buffer(new T[copy._size])
   {
      T* source = copy._buffer.get();
      T* dest = _buffer.get();
      std::copy(source, source + copy._size, dest);
   }

   // copy assignment operator
   Buffer& operator=(const Buffer& copy)
   {
      if(this != &copy)
      {
         _name = copy._name;

         if(_size != copy._size)
         {
            _buffer = nullptr;
            _size = copy._size;
            _buffer = _size > 0 > new T[_size] : nullptr;
         }

         T* source = copy._buffer.get();
         T* dest = _buffer.get();
         std::copy(source, source + copy._size, dest);
      }

      return *this;
   }

   // move constructor
   Buffer(Buffer&& temp):
      _name(std::move(temp._name)),
      _size(temp._size),
      _buffer(std::move(temp._buffer))
   {
      temp._buffer = nullptr;
      temp._size = 0;
   }

   // move assignment operator
   Buffer& operator=(Buffer&& temp)
   {
      assert(this != &temp); // assert if this is not a temporary

      _buffer = nullptr;
      _size = temp._size;
      _buffer = std::move(temp._buffer);

      _name = std::move(temp._name);

      temp._buffer = nullptr;
      temp._size = 0;

      return *this;
   }
};

template <typename T>
Buffer<T> getBuffer(const std::string& name) 
{
   Buffer<T> b(name, 128);
   return b;
}
int main()
{
   Buffer<int> b1;
   Buffer<int> b2("buf2", 64);
   Buffer<int> b3 = b2;
   Buffer<int> b4 = getBuffer<int>("buf4");
   b1 = getBuffer<int>("buf5");
   return 0;
}

The default copy constructor and copy assignment operator should look familiar. What’s new to C++11 is the move constructor and move assignment operator, implemented in the spirit of the aforementioned move semantics. If you run this code you’ll see that when b4 is constructed, the move constructor is called. Also, when b1 is assigned a value, the move assignment operator is called. The reason is the value returned by getBuffer() is a temporary, i.e. an rvalue.

You probably noticed the use of std::move in the move constructor, when initializing the name variable and the pointer to the buffer. The name is actually a string, and std::string also implements move semantics. Same for the std::unique_ptr. However, if we just said _name(temp._name) the copy constructor would have been called. For _buffer that would not have been even possible because std::unique_ptr does not have a copy constructor. But why wasn’t the move constructor for std::string called in this case? Because even if the object the move constructor for Buffer is called with is an rvalue, inside the constructor it is actually an lvalue. Why? Because it has a name, “temp” and a named object is an lvalue. To make it again an rvalue (and be able to invoke the appropriate move constructor) one must use std::move. This function just turns an lvalue reference into an rvalue reference.

UPDATE: Though the purpose of this example was to show how move constructor and move assignment operator should be implemented, the exact details of an implementation may vary. An alternative implementation was provided by Member 7805758 in the comments. To be easier to see it I will show it here:

Collapse | Copy Code

template <typename T>
class Buffer
{
   std::string          _name;
   size_t               _size;
   std::unique_ptr<T[]> _buffer;

public:
   // constructor
   Buffer(const std::string& name = "", size_t size = 16):
      _name(name),
      _size(size),
      _buffer(size? new T[size] : nullptr)
   {}

   // copy constructor
   Buffer(const Buffer& copy):
      _name(copy._name),
      _size(copy._size),
      _buffer(copy._size? new T[copy._size] : nullptr)
   {
      T* source = copy._buffer.get();
      T* dest = _buffer.get();
      std::copy(source, source + copy._size, dest);
   }

   // copy assignment operator
   Buffer& operator=(Buffer copy)
   {
       swap(*this, copy);
       return *this;
   }

   // move constructor
   Buffer(Buffer&& temp):Buffer()
   {
      swap(*this, temp);
   }

   friend void swap(Buffer& first, Buffer& second) noexcept
   {
       using std::swap;
       swap(first._name  , second._name);
       swap(first._size  , second._size);
       swap(first._buffer, second._buffer);
   }
};

Conclusions

There are many more things to say about C++11; this was just one of many possible beginnings. This article presented a series of core language and standard library features that every C++ developer should use. However, I recommend you additional readings, at least for some of these features.


Anatomy of HTML5/Javascript Single Page Application


 

 

 

Introduction

What is  Single Page Application (SPA)?

Ordinary HTML applications/web-sites fetch each page from the server every time the user wants to go to a new page. SPA applications, however, bring all the pages of the application on the client’s browser at the beginning and  use JavaScript in order to switch between the pages making parts of HTML visible and invisible depending on which page  is chosen. This makes the HTML application as responsive as a native or Silverlight application, since the navigation between the pages does not require a round trip to the server. This advantage comes at the expense of a higher  application loading time. There are some ways to speed up the loading of an SPA application, making the  SPA loading experience for the user the same as when loading a usual HTML application, but  this topic is beyond this article.

If you think of it, an SPA application is very similar to a Silverlight application, in that most Silverlight applications load all the pages at the beginning and later allow the users to navigate between the pages without calling the server. So understanding of the SPA concepts should come very naturally to Silverlight developers.

Navigation State

In its generic form, the browser navigation maps a unique URL to the specific navigation state of the browser application. The “navigation state of the application” determines which pages or regions within the application are shown or hidden or how they are shown.

The browser interprets the URL and sets the application to the corresponding state. This is required for e.g. enabling the user to navigate the browser application by pressing the browser “back” and “forward” navigation buttons (the browser stores the URLs and when the user presses one of the browser navigation buttons the URL changes and the application state changes correspondingly). Also, this is useful when some external page refers to some specific page (or state) within the application which is not the application’s default page.

The reverse is also true: once the state of the application changes, e.g. because the user presses a tab or a hyperlink to move to a different page, the browser URL should also change to the one corresponding to the new state.

For the ordinary (non-SPA) HTML applications the navigation comes naturally (the page loads from the server based on the corresponding URL). The SPA applications, however, need to use some JavaScript magic in order to achieve the one-to-one mapping between the URLs and the navigation states of the application. Here we present a new functionality that makes the SPA navigation easier to achieve than by using other already existing frameworks.

The same navigation concepts can apply to any native single window/multipage applications especially to those built for smart phones and tablets and time permitting, I am going to write more articles about it.

Composition of an SPA Application

In my experience, building SPA application results in large HTML files since the application consists of multiple pages and all of them are loaded together. Large HTML files can be difficult to understand and modify. I created functionality allowing to split SPAs into multiple files and load and assemble them all on the client. This functionality is also discussed here.

BPF Framework

Being a great fan of WPF and Silverlight, I ambitiously called the new framework BPF standing for  Browser Presentation Foundation. Its ultimate purpose is to provide the capabilities one can find  in WPF and Silverlight and more. Currently it provides some generic purpose utility functionality,  navigation and composition capabilities which will be described below. Composition part of the  framework depends on JQuery, the rest of the framework is self-sufficient, and can be used  without JQuery installed.

There are two SPAs that have been built with an earlier version of BPF library: my own business website -    awebpros.com and    paperplusne.com. Note that paperplusne.com website does not have correct pricing data yet for all its items (for items without pricing data I put $1000 as their price). You can still order some  plastic-ware through it and someone will contact you back about the prices.

SPA Server Communications

Just like a Silverlight or a desktop application, the SPA application can minimize the amount of information it loads from the server by getting only the required data from the server (usually in JSON form) and not the generated HTML code as ordinary HTML applications do. I provide some examples of an SPA communicating with     the server within this article.

Organization of this Article

We present the simplest possible samples of the ordinary and SPA  HTML/JavaScript sites. We talk about the differences between them.

We discuss the navigation and present the navigation capabilities of the BPF framework.

We discuss the composition using BPF framework.

We talk about SPA communications with the server using ASP.NET MVC and provide corresponding examples.

Important Note: This article concentrates on the business logic and not on the UI design. We present the SPAs built in the simplest possible way without any concern about how ugly they look.

Prerequisites

You need to have some knowledge of HTML and JavaScript in order to read and understand this article.  I refer to HTML5, JavaScript, Knockout, JQuery, Guide for Recovering Silverlight/WPF/C# Addicts. Part 1 – JavaScript and DOM as a good  HTML/JavaScript primer.

Throughout this article, I use some very basic JQuery functionality to detect when the HTML document is loaded  and also to provide a multiplatform way of binding to the DOM events, so some understanding of JQuery functionality  is needed. A couple of paragraphs from  JQuery and  DOM Event should cover this information.

When discussing composition we also use JQuery selectors. You can follow the JQuery Selectors link to learn about them.

I am using JQuery-UI tabs control extensively for navigation  but anything related to that is explained in the text.

Part that covers communications with the server might require some basic understanding of ASP MVC, even though  we try to explain everything within the article itself.

Part of a Larger Series

This article can be considered part 3 of   “HTML5, JavaScript, Knockout, JQuery, Guide for Recovering Silverlight/WPF/C# Addicts” series which also contain       HTML5, JavaScript, Knockout, JQuery, Guide for Recovering Silverlight/WPF/C# Addicts. Part 1 – JavaScript and DOM and       HTML5, JavaScript, Knockout, JQuery, Guide for Recovering Silverlight/WPF/C# Addicts. Part 2 – Solar System Animation built with SVG, Knockout and MVVM Pattern.  

SPA Basics

Presenting Two Page SPA and Two Page Ordinary HTML Application Samples

Here we present two very simple two-page HTML applications: one ordinary and the other SPA. The code for the ordinary HTML  application is located under TwoPageOrdinaryHTMLApp solution, while the code for the SPA is located under TwoPageSPA solution.

Both applications provide exactly the same user experience. There are two hyperlinks at the top of the HTML window  corresponding to two pages. Clicking on top hyperlink shows first page’s text, while clicking on the other one shows the  other page’s text:

The ordinary HTML application has two HTML pages Page1.htm and Page2.htm. Both have hyper links at the top of the page (one to itself and one to the other page) and the page text. For page1.htm page text is “This is page 1″ and it is colored red. For page2.htm the text is “This is page 2″ and it is colored blue. Here is the page1.htm code:

Collapse | Copy Code

<body>
    <!-- hyper links for choosing the page -->
    <ul>
        <li><a href="Page1.htm">choose page1</a></li>
        <li><a href="Page2.htm">choose page2</a></li>
    </ul>

    <!-- page 1 message colored in red -->
    <p style="font-size:40px;color:red">This is page 1</p>
</body>

To start the TwoPageOrdinaryHTMLApp, right click on Page1.htm file within the Visual Studio’s solution explorer and choose “View in Browser” option if you want to view it in the default browser or “Browse with” option if you want to choose the browser.  You can switch between the pages by clicking the hyperlinks at the top.

The SPA solution uses JQuery (if you open Scripts folder you will see a bunch of JQuery files).  You can install JQuery as a NuGet package as described in JQuery.

There is only one HTML file within TwoPageSPA project: Index.html. You can start the application by right clicking on this file within solution explorer and choosing “Run in Browser”. Index.html has HTML part containing the hyperlinks and text for both page. It also has a JavaScript code for switching between the pages.

Here is the HTML code within Index.html file:

Collapse | Copy Code

<body>
    <ul>
        <!-- href='#' is needed only to help the links look like links -->
        <li><a id="page1Link" href="#">choose page1</a></li>
        <li><a id="page2Link" href="#">choose page2</a></li>
    </ul>

    <!-- page 2 message colored in blue -->
    <!-- in the beginning page2 is not visible (display set to 'none') -->
    <p id="page2" style="font-size:40px;color:blue;display:none">This is page 2</p>

    <!-- page 1 message colored in red -->
    <p id="page1" style="font-size:40px;color:red" >This is page 1</p>

</body>

As you can see, the page links do not contain valid references – their href property is set to ‘#’  just so that they would look and behave like links (have bluish color and change the mouse cursor to “hand”).

Both pages’ text is placed below the links. Page 2 text is not visible in the beginning   (its display property is set to none and because of    that, it is placed first so that whatever HTML code follows it won’t be shifted down because of it.

Page switching is done by JavaScript code placed below the HTML code:

Collapse | Copy Code

    // use $(document).ready function to
    // make sure that the code executes only after the document's 
    // DOM has been loaded into the browser.
    $(document).ready(function () { 
        // when page1Link link is clicked, page1 shows, 
        // page2 hides
        $(page1Link).bind("click", function () {
            $(page1).show();
            $(page2).hide();
        });

        // when page2Link link is clicked, page2 shows, 
        // page1 hides
        $(page2Link).bind("click", function () {
            $(page1).hide();
            $(page2).show();
        });
    });

We use JQuery’s bind function to attach event handlers to click events on the hyperlinks. When the event fires we show the contents of one of the pages and hide the contents of the other page.

One can see, however, there is a difference in behaviors of the two applications. When you change pages in the ordinary HTML application, the browser URL also changes (e.g. from http://localhost:23033/Page1.htm to http://localhost:23033/Page2.htm). After switching the pages, you can use “back” button on your browser to go to the previous page. Also if you want the users to access Page2.htm without accessing  Page1 (which is a default page for the application) you can simply give a hyperlink http://localhost:23033/Page2.htm pointing straight  to Page2.

If you try to switch pages in the SPA, however, you will notice that the URL does not change, back button is not working and there is no way to give the users a straight link to page2. This problem will be addressed shortly  in a section of the article dedicated to SPA navigation.

Using JQuery UI Tabs for SPA Pages

It looks nicer to have tabs instead of hyperlinks when you want to switch between the pages.  JQuery UI tabs can be used for this purpose.

JQuery UI is a GUI package built on top of JQuery. You can install it via NuGet in the same fashion as JQuery.

The code sample using JQuery UI tabs is located under TwoPagesSPAWithTabs solution. It consists of Index.htm file as well as the files from JQuery and JQuery UI packages. Index.htm file contains reference to a JQuery UI  style sheet: <link href="Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" /> at the top of the page (the style sheet is part of the JQuery UI package installation).

Here is the HTML code within Index.htm file:

Collapse | Copy Code

<body>
    <ul id="pageTabs">
        <!-- hrefs of the links point to the ids of the pages' contents -->
        <li><a href="#page1">choose page1</a></li>
        <li><a href="#page2">choose page2</a></li>
    </ul>

    <!-- page 1 message colored in red -->
    <p id="page1" style="font-size:40px;color:red" >This is page 1</p>

    <!-- page 2 message colored in blue -->
    <p id="page2" style="font-size:40px;color:blue">This is page 2</p>
</body>

Note that the href attributes of the hyperlinks at the top of the code are pointing to ids of the  HTML tags containing page content (e.g. hyperlink with  href="#page1" points to the tag <p id="page1" ...).  This is to let JQuery UI functionality figure out which content belongs to which tab.

The JavaScript code is also very simple:

Collapse | Copy Code

    $(document).ready(function () {
        $("body").tabs(); // turns the hyperlinks into tabs
    });

Here is how the application looks:

Just like in previous SPA sample, the URL is not connected to the tabs – changing tabs won’t change the  URL and changing URL won’t change the tabs.

BPF Framework and Navigation

Here we present navigation functionality of the BPF framework.

Many SPAs use Sammy.js framework for the navigation.   Sammy.js allows to map different URL hashes into  various JavaScript functions. When SPA has a lot of different navigation states with some possible hierarchy, such mapping might be different to implement. BPF library, however, implements the mapping between the navigation states and the URL hashes naturally and with very little extra code.

There is a limitation to the current version of BPF framework, in that it relies on    hashchange document event to detect the changes of the hash and change the  navigation states of the SPA. IE7 does not support hashchange event  so the navigation functionality will on work on it. The share of    IE7 browser users is currently smaller than 1% and rapidly declining, so I believe this issue  does not have to be addressed.

Code for BPF framework is located under BPF folder. It is also available from  github.com/npolyak/bpf. The only file you  need in order to access all of its functionality is bpf.min.js; so far (in the beginning of December 2012, it is pretty small – about 12Kb). This file  was obtained by bundling and minification of other JavaScript files which can  also be found in BPF folder and to which I will be referring from time to time.

Two Page SPA with Navigation

We’ll start by using BPF functionality to modify the simple two page SPA with tabs presented above in such a way that it can be navigated. The sample is located under TwoPageSPAWithNavigation solution.  The only difference between this project and TwoPageSPAWithTabs lies in JavaScript code at the bottom of Index.html file. In TwoPageSPAWithTabs project JavaScript code consisted of one line $("body").tabs(); within $(document).ready() method. The purpose of this line was to turn the hyperlinks into the JQuery  tabs with the corresponding content. The JavaScript code within TwoPageSPAWithNavigation is more complex:

Collapse | Copy Code

// get the tabs DOM elements
var tabs = $("body").tabs(); // turns the hyperlinks into tabs

// JQTabsNavAdaptor is a special constructro that adapts
// the JQuery tabs to become usable by the navigation framework
var tabsAdaptor = new bpf.nav.JQTabsNavAdaptor(tabs);

// create the navigation framework node
var tabNode = new bpf.nav.Node(tabsAdaptor);

// connect the navigation framework node to the browser's url hash
bpf.nav.connectToUrlHash(tabNode);

// set the url to correspond to the 
return bpf.nav.setKeySegmentToHash(tabNode);

Do not try to understand it all, since detailed navigation functionality design will be discussed shortly. In short, we use bpf.nav.Node functionality to connect the navigation states to the parts of the browser url.  bpf.nav.JQTabsNavAdaptor adapts JQuery tabs so that the resulting adapted object has methods expected by bpf.nav.Node. The line bpf.nav.connectToUrlHash(tabNode) makes a two way connection between the nodes and the URL (nodes react to URL and vice versa).  Last line bpf.nav.setKeySegmentToHash(tabNode) sets the initial URL to match  the one obtained from bpf.nav.Nodes structure.

Running the sample shows SPA very similar to TwoPageSPAWithTabs, but the tabs have unique URL mapped to  them and when you change the tabs, the URL also changes. Correspondingly “Back” and “Forward” browser buttons now work and switch between the tabs. Also typing “http://localhost:48476/Index.html#page2.&#8221; for a URL in a browser, will get you straight to the second tab.

A More Complex Example With JQuery Tabs

HierarchicalSPAWithNavigation sample presents a more interesting of tab hierarchy. The top level tabs contain sub-tabs. Each tab/sub-tab combination maps to its own URL.

Try starting the application and playing with the tabs. Here is how the application looks:

Pay attention that we show SubPage2 within Page2. This combination  corresponds to the URL hash: “#page2.page2SubTab2.”.  If we change the tabs, the hash will change accordingly.

You can see that the hash always start with ‘#’ and ends with ‘.’ character.   The links corresponding to different levels of the navigation state hierarchy are separated  by the period (‘.’) character. Such links in this sample, match the href  values of the links of the tabs stripped of ‘#’ prefix character.

Here is the code for creating connecting the navigation (again do not try very hard to understand it as  we’ll discuss it in the next subsection):

Collapse | Copy Code

// get the tabs DOM elements
var tabs = $("body").tabs(); // turns top level hyperlinks into tabs

var page1SubTabs = $("#page1SubTabs").tabs(); // turns page 1 hyperlinks into tabs

var page2SubTabs = $("#page2SubTabs").tabs(); // turns page 2 hyperlink into tabs

// creates the top level node (JQTabsNavAdaptor is used).
var topLevelNode = bpf.nav.getJQTabsNode(tabs);

// creates a child node and adds it to top level node
// as child of "page1".
bpf.nav.addJQTabsChild(topLevelNode, "page1", page1SubTabs);

// creates a child node and adds it to top level node
// as child of "page2".
bpf.nav.addJQTabsChild(topLevelNode, "page2", page2SubTabs);

// connect the navigation framework to the browser's url hash
bpf.nav.connectToUrlHash(topLevelNode);

// set the url to correspond to the current selection pattern
return bpf.nav.setKeySegmentToHash(topLevelNode);

Detailed Design of the Navigation Functionality

Navigation functionality is located under “namespace” bpf.nav within BPF library. It relies on the bpf.utils functionality and also parts of it depend on JQuery and JQuery UI (though it can work without them).

The purpose of Navigation functionality is to allow the developers to   define a number of navigation states within an SPA and  map each of the states into a unique browser URL so that when the state changes  the URL changes also and vice versa – the URL change triggers the navigation  state change.

The navigation state is assumed to be hierarchical – there can be a number of  states at the top level (e.g. page 1 and page 2 from the previous sample). Each   one can have sub-states (sub-pages). Each of the sub-states can have its own  sub-states etc. The total navigation state of the application   is determined by the unique selection of states at each level (or level states).   Each level state maps to a link bound by period (‘.’) characters within the URL hash.   It is attached to a link corresponding to the parent level state.   The image below depicts a sample of the state hierarchy with the tree links corresponding  to the level states and the hash strings shown next to the corresponding end nodes: e.g.   Page1/SubPage2 selection will result in hash=”#Page1.SubPage2.”:

Each part of the URL’s hash bound by periods we call hash segment. For example   hash “#Page1.SubPage2″ has two segments: “Page1″ and “SubPage2″. Each segment maps  into the level state selected at that level.  At each level no more than one level state can be selected (sometimes,   it is convenient to assume that no level state is selected at some level).

Navigation states consist of level states. Each navigation node can have  several level child states that belong to it. One or none of these level child states  may be selected as the current level state. Each of the level states has a   string associated with it. This string uniquely identifies  that state among the children states of the same node. This string becomes a segment bound  by two period characters within the URL’s hash when the level state is selected.  The total hash is uniquely determined by the sequence of such segments corresponding to  the level states starting from the higher level states and going down to the more  refined levels.

The main functionality for capturing information about the tree of level states is bpf.nav.Node  located within NavigationNode.js file.  It kind of extends or subclasses (in C# sense) the functionality provided by bpf.nav.NodeBase located in  NavigationNodeBase.js file. This subclassing is achieved by bpf.nav.Node constructor  calling bpf.nav.NodeBase constructor within its code. We need subclassing because another class    bpf.nav.ProductNode is also derived from the same bpf.nav.NodeBase class.    bpf.nav.ProductNode functionality as will be discussed below. This inheritance relationship is   shown at the diagram below:

bpf.nav.Node references its parent and children (if any). bpf.nav.Node‘s parent and children  are also derived from bpf.nav.NodeBase class. The children of bpf.nav.Node are accessible by  string keys via function bpf.nav.NodeBase.getChild(key). The key maps into the corresponding segment   of the URL’s hash.

Each bpf.nav.Node object wraps some other object in charge of switching states at the node’s level.  As the above samples show, such object can be JQuery UI tabs object. bpf.nav.Node assumes that the   wrapped object satisfies certain requirements – it should have some methods and fields – in Java or C# that requirement  would be that the wrapped object should implement some interface. Here is the interface that it should implement written in  C# notations:

Collapse | Copy Code

public interface ISelectable
{
    // event that fires when a selection changes at the selectable
    // object's level. 
    // This event is implemented as bpf.nav.SimpleEvent in JavaScript
    event Action onSelectionChagned;

    // returns the currently selected key (hashSegment)
    // if no key is selected, it returns null
    string getSelectedKey();

    // does the selection specified by the key (or hashSegment)
    void select(string key);

    // unselects the currently selected key (if any and if the object allows it).
    void unselect();
}

Most entities within JavaScript do not support the above interface so we have to use an adaptor to  adapt the objects we are dealing with to ISelectable interface. The adaptor for JQuery UI  tabs object is called bpf.nav.JQTabsNavAdaptor and it is part of the BPF library.

Adaptor contains the object that controls the selection (in this case it is JQuery UI tabs object) and   implements ISelectable interface by providing the methods that bpf.nav.Node expects.

Another adaptor built into BPF – a check box adaptor comes with bpf.nav.CheckboxNavAdaptor class.   It provides a way to associate the level states with checkbox’s checked and unchecked states.

bpf.nav.Node (via bpf.nav.NodeBase) has the following important methods:

  • setSelectedKeySegments(urlHash) – sets the selections for the node and its descendant    to match the segments within URL’s hash passed as a string to the function
  • getTotalHash() – returns a URL’s hash that corresponds to the selections within the       node itself and its descendants. The hash has a leading pound (‘#’) and trailing period (‘.’)       characters.

These two methods provide a way to update the selection within some selectable objects (e.g. JQuery UI tabs)   once the URL’s hash changes and vice versa – to change the URL once a selection changes within the    bpf.nav.Node hierarchy.

View Model Selection Example

This section requires some knowledge of Knockoutjs library.   You can learn about Knockoutjs by using this link or many other  resources including       Solar System Animation built with SVG, Knockout and MVVM Pattern.  

This section’s sample is located under ParamNavigationTest solution. We have a View Model created  by the functionality within the file StudentViewModel.js file under Scripts/ViewModels directory. It defines  a collection of studentVM.students of objects of type Student. Each Student  has a name field and a collection of course objects. Each course has two fields   courseName and grade. The View Model studentVM has selectedStudent   Knockoutjs observable field. Also each Student object  has an observable selectedCourse field.

The View is located within HTML/Index.html file. It provides hyperlinks to the Student objects  at the top level. The links display student’s name. Once a link is clicked the corresponding student is selected and  the browser window shows the name of the courses taken by the selected student under the student’s hyperlink.   When the course link is clicked the browser shows the student name, course name and the student’s grade for that course:

Our task is to provide a unique URL hash for each student – course selection.

We can, of course, use the bpf.nav.Node functionality described above for every student and course object.   This, however, can be problematic if the number of such objects is very high or if the student or course collections  change throughout the application.

BPF library has a class bpf.nav.FactoryNode located within NavigationFactoryNode.js file,   that produces bpf.nav.Node objects as they are needed  by the application and adds them to their parent node’s childNodes collection.

We use bpf.nav.KoObservableNavAdaptor as an adaptor object to adapt the observable   objects. bpf.nav.KoObservableNavAdaptor constructor takes 3 parameters:

  • the observable
  • the function to get the object by the hash segment (or key) from the View Model collection
  • the function to get the key from each object within View Model collection

 

Here is how we connect the navigation states to the View Model within Index.html file:

Collapse | Copy Code

// we create the adaptor for the selected student observable
var studentLevelObservableAdaptor =
    new bpf.nav.KoObservableNavAdaptor
    (
        studentVM.selectedStudent,

        // key to student function
        function (key) {
            var foundStudent = _.chain(studentVM.students).filter(function (student) {
                return student.name === key;
            }).first().value();

            return foundStudent;
        },

        // student to key function
        function (student) {
            return student.name;
        }
    );

var topLevelNode = new bpf.nav.FactoryNode(
    studentLevelObservableAdaptor,
    null,

    // child node producing function
    function (key, data) {

        var childObj = data.getChildObjectByKey(key);

        if (!childObj)
            return;

        // create adapted child object
        var adaptedChildObj =
            new bpf.nav.KoObservableNavAdaptor
            (
                childObj.selectedCourse,
                function (courseKey) {
                    return _.chain(childObj.courses).
                        filter(function (universityCourse) {
                            return universityCourse.courseName === courseKey;
                        }).first().value();
                },
                function (course) {
                    return course.courseName;
                }
            );

        // create the node
        return new bpf.nav.Node(
            adaptedChildObj
        );
    }
);

bpf.nav.connectToUrlHash(topLevelNode);

bpf.nav.setKeySegmentToHash(topLevelNode);

Cartesian Product Navigation

Suppose that your browser is divided into two halves. Each of the halves has tabs. You can select one tab in each of the  halves. You also want to assign a URL for every possible tab combination. The resulting space of navigation states  will be a Cartesian products of the states within each of the halves of the browser.

We can further complicate the task by dividing the browser into more than two parts. Also we can assume that  such Cartesian product can occur not only at the top state, but at any state level.

SimpleProductNavigationTest solution contains precisely the scenario we described in the beginning of this section.   The browser page is divided into two parts. Each part has tabs. We record every combination of tab selections  in both parts of the page:

Note that total URL hash for on the figure above is “#(topics/TopicA)(othertopics/SomeOtherTopicA).”. The parts  of the hash corresponding to the components of the Cartesian product are placed within a parenthesis.   The part of the hash within a parenthesis starts with a key that uniquely identifies that part within  the Cartesian product. The key is separated from the rest of the string within the parenthesis by a forward slash.

We use bpf.nav.ProductNode to map the URL hash into the Cartesian product of the states. Its usage example  is located at the bottom of Index.html file within SimpleProductNavigationTest project:

Collapse | Copy Code

// create topics JQuery UI tabs
var topics = $("#MyTopics").tabs();

// create otherTopics tabs
var otherTopics = $("#SomeOtherTopics").tabs();

// top level node is a product node for
// the Cartesian product of the states
var topLevelNode = new bpf.nav.ProductNode();

// add "topics" node to be a child of topLevelNode under key "topics"
bpf.nav.addJQTabsChild(topLevelNode, "topics", topics);

// add "otherTopics" node to be a child of topLevelNode under key "othertopics"
bpf.nav.addJQTabsChild(topLevelNode, "othertopics", otherTopics);

// create the one to one relationship between the states and the URL
bpf.nav.connectToUrlHash(topLevelNode);

// change the original URL to be based on the navigation states
bpf.nav.setKeySegmentToHash(topLevelNode);

bpf.nav.ProductNode is located within ProductNavigationNode.js file. Just like bpf.nav.Node,  it is kind of a sub-class of bpf.nav.NodeBase. It overrides the implementation  of the functions setSelectedKeySegmentsRecursive, getUrlRecursive  and chainUnselect.

A considerably more complex example can be found in ComplexProductNavigationTest solution. It involves   a long sequence of tabs within tabs with Cartesian products occurring at two levels – the top one and   under TopicA tab.

Here is how the SPA looks:

The total hash part of the URL for the figure above is   “#(topics/TopicA.(a1subs1/A1Subtopic1.A1Sub1Sub2)(a1subs2/A2Subtopic2))(othertopics/SomeOtherTopicA).”.  You can play with the application to see that the browser navigation buttons are working indeed.

Here is the HTML code of the application:

Collapse | Copy Code

<table>
    <tr>
        <td style="vertical-align: top">
            <div id="MyTopics">
                <ul>
                    <li><a href="#TopicA">TopicA</a></li>
                    <li><a href="#TopicB">TopicB</a></li>
                </ul>

                <div id="TopicA">
                    My topic A
                    <table>
                        <tr>
                            <td style="vertical-align: top;">
                                <div id="A1Subtopics">
                                    <ul>
                                        <li><a href="#A1Subtopic1">A1Sub1</a></li>
                                        <li><a href="#A1Subtopic2">A1Sub2</a></li>
                                    </ul>

                                    <div id="A1Subtopic1">
                                        A1 Sub Topic1
                                        <div id="A1Sub1Sub">
                                            <ul>
                                                <li><a href="#A1Sub1Sub1">A1S1S1</a></li>
                                                <li><a href="#A1Sub1Sub2">A1S1S2</a></li>
                                            </ul>
                                            <div id="A1Sub1Sub1">A1 Sub1 Sub1</div>
                                            <div id="A1Sub1Sub2">A1 Sub1 Sub2</div>
                                        </div>
                                    </div>
                                    <div id="A1Subtopic2">A1 Sub Topic2</div>
                                </div>
                            </td>
                            <td style="vertical-align: top;">
                                <div id="A2Subtopics">
                                    <ul>
                                        <li><a href="#A2Subtopic1">A2Sub1</a></li>
                                        <li><a href="#A2Subtopic2">A2Sub2</a></li>
                                    </ul>

                                    <div id="A2Subtopic1">A2 Sub Topic1</div>
                                    <div id="A2Subtopic2">A2 Sub Topic2</div>
                                </div>

                            </td>
                        </tr>
                    </table>
                </div>
                <div id="TopicB">
                    The Topic B
                </div>
            </div>
        </td>
        <td style="vertical-align: top">
            <div id="SomeOtherTopics">
                <ul>
                    <li><a href="#SomeOtherTopicA">AnotherA</a></li>
                    <li><a href="#SomeOtherTopicB">AnotherB</a></li>
                </ul>
                <div id="SomeOtherTopicA">Some Other A </div>
                <div id="SomeOtherTopicB" style="background-color: pink">Some Other B</div>
            </div>
        </td>
    </tr>
</table>

And here is the JavaScript code within $(document).ready() function:

Collapse | Copy Code

  // create topics JQuery UI tabs
var topics = $("#MyTopics").tabs();

// create otherTopics tabs
var otherTopics = $("#SomeOtherTopics").tabs();

var A1Subtopics = $("#A1Subtopics").tabs();

var A2Subtopics = $("#A2Subtopics").tabs();

var A1Sub1Sub = $("#A1Sub1Sub").tabs();

// top level node is a product node for
// the Cartesian product of the states
var topLevelNode = new bpf.nav.ProductNode();

// add "topics" node to be a child of topLevelNode under key "topics"
var topicsNode = bpf.nav.addJQTabsChild(topLevelNode, "topics", topics);

// add "otherTopics" node to be a child of topLevelNode under key "othertopics"
bpf.nav.addJQTabsChild(topLevelNode, "othertopics", otherTopics);

var aSubtopicsProductNode = new bpf.nav.ProductNode();

topicsNode.addChildNode("TopicA", aSubtopicsProductNode);

var A1SubNode = bpf.nav.addJQTabsChild(aSubtopicsProductNode, "a1subs1", A1Subtopics);
bpf.nav.addJQTabsChild(aSubtopicsProductNode, "a1subs2", A2Subtopics);

bpf.nav.addJQTabsChild(A1SubNode, "A1Subtopic1", A1Sub1Sub);

// create the one to one relationship between the states and the URL
bpf.nav.connectToUrlHash(topLevelNode);

// change the original URL to be based on the navigation states
bpf.nav.setKeySegmentToHash(topLevelNode);

Using BPF Framework for SPA Composition

As I mentioned in Introduction, SPA might result in large HTML files due to the fact that all its pages  are loaded together and switching the pages simply means that parts of HTML change their visibility.

BPF framework provides a way to break HTML functionality into smaller files (called BPF plugins or  simply plugins) and assemble all of them together on the client side. It also allows the plugins   to refer to some other plugins creating a plugin hierarchy. Moreover, you can place JavaScript code  dealing with the functionality provided by the plugin into the same HTML file and later call this functionality  either during the composition or at a later stage. This was my attempt to   imitate the WPF/Silverlight code-behind concept within HTML/JavaScript universe.

All of the BPF composition related functionality is located within Composite.js file and it relies heavily  on JQuery.

Simple Plugin Sample

Let us take a look at the sample under SimpleCompositionSample project. HTML directory of this project  contains two html files Index.html – the main file and APlugin.html – a file containing   the plugin code.   To start the application, right click on Index.html file within Solution Explorer and choose   “View in Browser” option.

Here is the HTML code within Index.html file:

Collapse | Copy Code

<div style="font-size:30px;color:red">This is the main Module</div>
<img id="busyIndicator" src="../Images/busy_indicator.gif" style="vertical-align:central;margin-left:50%" />

<!-- plugin will get into this div below -->
<div id="APluginContainer1"></div>

<!-- call plugin's function to change its color to 'blue' for the plugin above -->
<button id="changePluginColorButton1">Change 1st Plugin Text to Blue</button>

<!-- plugin will get into this div below -->
<div id="APluginContainer2" style="margin-top:40px"></div>

<!-- call plugin's function to change its color to 'blue' for the plugin above -->
<button id="changePluginColorButton2">Change 2nd Plugin Text to Blue</button>

The only text visible within main HTML file is “This is the main Module”.  There are two <div> tags for inserting plugin content:   “APluginContainer1″ and “APluginContainer2″. Each one of them has a   button under it that calls the plugin’s code-behind to change  the color of the text of the corresponding plugin instance to blue.

You may notice that the same plugin is being inserted into two places within the main module.

Here is the JavaScript code of Index.html:

Collapse | Copy Code

// this event will fire after all the plugins and their
// descendant plugins are loaded
var compositionReady = new bpf.utils.EventBarrier();

// the composition ready event fires after everything all the plugins
// and their descendants have been loaded into the main module.
compositionReady.addSimpleEventHandler(function (success) {
    $("#busyIndicator").hide();

    $("#changePluginColorButton1").click(function () {

        // after changePluginColorButton1 is clicked, the
        // the function changeColorBackToBlue defined within the plugin
        // will be called and will only affect APluginContainer1
        bpf.control("#APluginContainer1").call("changeColorToBlue");
    });

    // after changePluginColorButton2 is clicked, the
    // the function changeColorBackToBlue defined within the plugin
    // will be called and will only affect APluginContainer2
    $("#changePluginColorButton2").click(function () {
        bpf.control("#APluginContainer2").call("changeColorToBlue");
    })
});

// gets the plugin from file APlugin.html and inserts it into the 
// element pointed to by the selector "#APluginContainer1"
bpf.cmpst.getPlugin("APlugin.html", null, "#APluginContainer1", compositionReady);

// gets the plugin from file APlugin.html and inserts it into the 
// element pointed to by the selector "#APluginContainer2"
bpf.cmpst.getPlugin("APlugin.html", null, "#APluginContainer2", compositionReady);

The two bpf.cmpst.getPlugin calls at the bottom,   load the plugin into the main module inserting it into two different places within the DOM.   The compositionReady  event handler is called after all the plugins and their descendants  are loaded into the main module. It hides the “busyIndicator” and  it assigns the callback to the buttons’ events calling changeColorToBlue  function of the plugin’s code=behind:

Collapse | Copy Code

bpf.control("#APluginContainer1").call("changeColorToBlue");

The function bpf.control(jquery-selector) returns   the code-behind for the plugin contained within the element pointed to  by the jquery-selector passed to it. We use the function   call() created by the BPF framework to call the  code-behind’s method. The function’s first argument is the name of the method  you want to call. If the method has some input arguments, you can   add them after the method name.

Now, let us take a look at the plugin code:

Collapse | Copy Code

<div id="aPlugin" style="font-size:25px">
    This is a plugin
</div>

<!--script tag should be marked by data-type="script-interface" in
    order for it to be recognized as containing the plugin's 'code-behind' -->
<script type="text/javascript" data-type="script-interface">
    (function () {
        // this function returns the plugin's 'code-behind' - 
        // a JSON object consisting the functions. Two function names are 
        // reserved "preRender" and "postRender" - the first executes 
        // before the plugin is inserted into the parent module's DOM
        // the second executes after the plugin is inserted into the parent's
        // module dome. 
        // other functions can be called at any later stage - at the developer's will
        // 'this' object for every function except for preRender contains the parameters
        // of the element into which this plugin attached. The most important parameter is
        // currentDOM - the DOM of the parent element.
        // All the JQuery selectors acting within the plugin should start with
        // this.currentDOM.find(... to make sure that we are only modifying our instance
        // of the plugin and not some other instances.
        // The other important field within "this" object is "codeBehind". It gives
        // access to the code-behind function returned below.
        // Note that all the function names should be in quotes in order for eval method
        // to work at the moment when the plugin is inserted into the plugin cache.
        return {
            "postRender": function (compositionReadyEventBarrier) {
                // change color to blue
                this.currentDOM.find("#aPlugin").css("color", "green");
            },
            "changeColorToBlue": function () {
                // change the color to blue
                this.currentDOM.find("#aPlugin").css("color", "blue");
            }
        };
    })();
</script>

The HTML of the plugin simply shows text “This is a plugin”.

The <script> tag marked with    data-type="script-interface" attribute is considered to contain  the plugin’s code-behind. There should only be one <script> attribute like that.  The rest of the script attributes can be added to the plugin in order to enhance intellisense, but   will be removed when the plugin is loaded into the main module. All the   JavaScript references contained in <script> required for the plugins to work  should be placed in the main module.

The code-behind <script> tag contains an anonymous function that returns  a JSON object defining various methods. There are two   predefined code-behind methods that are called (if they exist) when the plugin is loaded  into the main module: preRender and postRender – the first one is called  before and the second one after the plugin is loaded.

All the code-behind methods except for preRender receive a special object as   their this variable. This object contains currentDOM field  which is a JQuery DOM object for the element within the parent module into which   the plugin was attached.

Important Note: if you want to find a DOM element belonging to a plugin within the code-behind you should do it via a call to this.currentDOM.find(selector) function, not by  using $(selector). The reason is that if the same plugin is inserted in multiple places within the main module, unless you use this.currentDOM.find method, you’ll probably find multiple instances of the same plugin instead of that particular instance, so that all of your modification will be applied to multiple instances instead of the particular instance you need. BTW, note that that since our plugin has and id: id="aPlugin", and the plugin is inserted twice into the main module, you’ll have two different elements with the same id within the main module. It seemed to be working fine in my experience due to the fact that I was always using this.currentDOM.find to resolve the instance. If you feel that it is wrong (after all it is the ABCs of the HTML that there should be no two elements with the same id within the DOM), you can avoid using ids within plugins  and use unique class names instead.

The postRender function changes the color of the text of the plugin to green once  the plugin is inserted into the main module.

Code-behind’s method changeColorToBlue changes the color of the  plugin’s text to blue.

Here is how we call the changeColorToBlue function from the JavaScript code  of the main module (file Index.html):

Collapse | Copy Code

bpf.control("#APluginContainer1").call("changeColorToBlue");

When you run the application you will get the text for both instances of the plugin colored in green.  When you click the button under the corresponding plugin instance that plugin instance will turn blue,  while the other stays the same color.  Here is the image of the application after the top plugin instance’s button was clicked:

The text of the top plugin instance changed to blue, while the text of the bottom  plugin instance stayed green.

Chain of the Plugins Composition Sample

ChainOfPluginsCompositionSample solution contains a sample where the main module loads  a plugin, which, in turn load another plugin we call it sub-plugin.   All the HTML files of the sample are located  under HTML folder. Index.html is the file containing the main module. You can start the application  by right clicking on it and choosing “View in Browser” option.  Here is the image of the application once it starts:

The buttons change the color of the text of the plugin and sub-plugin correspondingly.

The code of Index.html file does not contain anything new in comparison to the previous sample. Most   “interesting” code is located within APlugin.html file:

Collapse | Copy Code

<div id="aPlugin" style="font-size:25px">
    This is a plugin

    <div id="subPluginContainer"></div>

    <Button id="changePluginColorButton">Change Plugin Color to Blue</Button>
    <Button id="changeSubPluginColorButton">Change SUB Plugin Color to Black</Button>
</div>
<script src="../Scripts/jquery-1.8.3.js"></script>
<script src="../Scripts/BPF/bpf.js"></script>
<script type="text/javascript" data-type="script-interface">
    (function () {
        return {
            "postRender": function (compositionReadyEventBarrier) {
                var self = this;

                // change color to green
                self.currentDOM.find("#aPlugin").css("color", "green");

                // create a child event barrier - it will fire
                // once the sub-plugin and all of its
                // descendants are loaded.
                // And the parent event barrier won't fire until it fires.
                var subCompositionReady = 
                    compositionReadyEventBarrier.createChildEventBarrier();

                subCompositionReady.addSimpleEventHandler(function () {
                    // changes the color of the plugin itself to blue.
                    $("#changePluginColorButton").click(function () {
                        self.currentDOM.find("#aPlugin").css("color", "blue");
                    });

                    // on changeSubPluginColorButton click call the sub-plugin's
                    // method changeColorToBlack
                    $("#changeSubPluginColorButton").click(function () {
                        bpf.control("#subPluginContainer", self).call("changeColorToBlack");
                    });
                });

                // get sub-plugin note that you need to pass 'this' object
                // as the second argument to getPlugin function
                bpf.cmpst.getPlugin("ASubPlugin.html", self, "#subPluginContainer", subCompositionReady);
            }
        };
    })();
</script>

Note that when we call getPlugin() function within the plugin, we pass self ( which is the same as this variable) as the second argument, not null as we do in the main module. Also note that in order to get access within a plugin to the code-behind object of the sub-plugin, we need to pass self as  the second argument to the bpf.control() function: bpf.control("#subPluginContainer", self).call("changeColorToBlack");.

Composition and Navigation Sample

CompositionAndNavigationSample solution shows how to combine BPF composition and navigation.  We create two tabs at the main module level. We also have tabs within a plugin.   The plugin is added to the content of one of the tabs within the main module. We use the   bpf.nav.Node objects create a navigation node around the plugin’s tabs and   connect it as a child of the main module’s node structure.   Here is the main modules code within Index.html file:

Collapse | Copy Code

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <link href="../Content/themes/base/jquery-ui.css" rel="stylesheet" />
    <title></title>
</head>
<body>
    <!-- links to be converted to tabs -->
    <ul id="pageTabs">
        <li><a href="#page1">Page1</a></li>
        <li><a href="#page2">Page2</a></li>
    </ul>

    <!-- page 1 message colored in red -->
    <div id="page1" style="color:red" >
        This is page 1

        <div id="pluginContainer"></div>
    </div>

    <!-- page 2 message colored in blue -->
    <div id="page2" style="color:blue">This is page 2</div>
</body>
</html>
<script src="../Scripts/jquery-1.8.3.min.js"></script>
<script src="../Scripts/jquery-ui-1.9.2.min.js"></script>
<script src="../Scripts/BPF/bpf.js"></script>

<script>
    $(document).ready(function () {

        // create the tabs, store a reference to the tabs.
        var topLevelTabs = $("body").tabs();

        // create the top level bpf.nav.Node object around the tabs.
        var topLevelNode = bpf.nav.getJQTabsNode(topLevelTabs);

        var compositionReady = new bpf.utils.EventBarrier();

        compositionReady.addSimpleEventHandler(function () {
            // this function is called after all the plugins are loaded (rendered)

            // we call "connectToParentNode" function on the plugin
            // passing the topLevelNode to it, in order to connect
            // the plugin's tabs to the bpf navigation framework.
            bpf.control("#pluginContainer").call("connectToParentNode", topLevelNode);

            // connect the navigation framework with the URL's hash
            bpf.nav.connectToUrlHash(topLevelNode);

            // update the current URL
            bpf.nav.setKeySegmentToHash(topLevelNode);
        });

        // get the plugin
        bpf.cmpst.getPlugin("APlugin.html", null, "#pluginContainer", compositionReady);
    });
</script>

To connect the plugin’s navigation node to that of the main module, we call function connectToParentNode on the plugin’s code-behind, passing the parent node  (topLevelNode) as a parameter to it:

Collapse | Copy Code

bpf.control("#pluginContainer").call("connectToParentNode", topLevelNode);

Here is the plugin’s code (from APlugin.html file):

Collapse | Copy Code

 <div id="subTabPlugin">
    <ul id="subTabs">
        <li><a href="#subPage1">SUB Page1</a></li>
        <li><a href="#subPage2">SUB Page2</a></li>
    </ul>

    <!-- page 1 message colored in red -->
    <div id="subPage1" style="color:green" >This is SUB page 1</div>

    <!-- page 2 message colored in blue -->
    <div id="subPage2" style="color:purple">This is SUB page 2</div>
</div>
<script src="../Scripts/jquery-1.8.3.min.js"></script>
<script src="../Scripts/jquery-ui-1.9.2.min.js"></script>
<script src="../Scripts/BPF/bpf.js"></script>
<script type="text/javascript" data-type="script-interface">
    (function () {
        var pluginTabs;

        return {
            "postRender": function (compositionReadyEventBarrier) {
                // create tabs within the plugin and store the
                // tab object to be used later
                pluginTabs = this.currentDOM.find("#subTabPlugin").tabs();
            },
            "connectToParentNode": function (parentNode) {
                // create the navigation node at the plugin level and 
                // connect it with the parent navigation node.
                bpf.nav.addJQTabsChild(parentNode, "page1", pluginTabs);
            }
        };
    })();
</script>

The method postRender creates the tabs out of the hyperlinks and stores the reference to them within the plugin by calling  pluginTabs = this.currentDOM.find("#subTabPlugin").tabs();.

Connecting to the parent’s navigation node is taken care of by the method  connectToParentNode. This method is called from the main module. (Of course we could have connected the navigation nodes within postRender function but we wanted to demonstrate more composition functionality by creating a separate method connectToParentNode and calling it from the main module).

Parameterized Plugins

ParameterizedPluginSample shows how to create instances of the same plugin that differ in their looks.  Just like in SimpleCompositionSample, two instances of the same plugin are inserted into the main module  contained within Index.html file:

Collapse | Copy Code

// gets the plugin from file APlugin.html and inserts it into the 
// element pointed to by the selector "#APluginContainer1"
bpf.cmpst.getPlugin(
    "APlugin.html",
    null,
    "#APluginContainer1",
    compositionReady,
    {
        fontSize: "50px",
        color: "blue"
    }
);

// gets the plugin from file APlugin.html and inserts it into the 
// element pointed to by the selector "#APluginContainer2"
bpf.cmpst.getPlugin(
    "APlugin.html",
    null,
    "#APluginContainer2",
    compositionReady,
    {                      // pass the object containing postRenderArguments
        fontSize: "20px", 
        color: "green"
    }
);

The last argument to bpf.cmpst.getPlugin function is the JSON object which can   be accessed from within postRender function of the plugin’s code-behind via   this.postRenderArguments object. Here is the code-behind of the plugin:

Collapse | Copy Code

 {
    "postRender": function (compositionReadyEventBarrier) {
        var fontSize = this.postRenderArguments.fontSize; // get font size from the arguments
        var color = this.postRenderArguments.color; // get color from the arguments

        this.currentDOM.find("#aPlugin").css("font-size", fontSize);
        this.currentDOM.find("#aPlugin").css("color", color);
    }  
}

As a result we have the same plugin text displayed with different font-size and color:

The top plugin instance has font size of 50px and blue color, while the bottom one -   20px and green color.

Generic Silverlight Plugin Sample

Here I describe a generic BPF plugin for Silverlight applications.

Silverlight apps are usually packaged as one file with .xap extension. In order to embed a  Silverlight app into a page, you have to have the page reference Silverlight.js file   (which comes from Microsoft). You also have to write the following HTML code within your  HTML application:

Collapse | Copy Code

This is a large chunk of HTML code and my idea was to create a BPF parameterized plugin for re-using it in multiple places within HTML applications. One of the parameters of the BPF plugin will be, of course, the Silverlight app’s URL. Other parameters might be needed for positioning  the application, e.g. width, height, margins.

You would probably want to know why Silverlight plugin is different from any other BPF plugin.   Why can’t we simply create a parameterized plugin using the information from the previous subsection?   My answer is “redirect your question to Microsoft”. The <object> tag behaves in a very strange way in  conjunction with JQuery on IE8 and IE9 – trying to use JQuery to parse the DOM of the object tag   totally mangles it. Besides, from my experience, the Silverlight app URL has  to be set before the HTML code is inserted into the main module – IE won’t change the Silverlight  application when the Silverlight URL changes if the code has already been inserted.   In fact it is because of these issues that I added preRender function to the   code-behind to be called before the plugin is added to the main module.

The code for this sample is located under SilverlighPluginSample solution. Here is what you get  if you run the application – (hey, after a week of toiling on this article I can  allow myself a bit of self promotion – AWebPros.com  is my company):

To get around the issues with Silverlight plugin that I describe above, we change the plugin code  substituting <object> tag for <myobject>. Also in order to place the URL parameter  in the correct place, we use “___XAPFilePlaceHolder___” string as a placeholder.   The substitution of these strings by the correct ones takes place within preRender  method, before the code is inserted into the main module. We get the HTML code  of the Silverlight plugin by using this.getDownloadedHtml() function  (which, within preRender method indeed returns the full plugin HTML code).

Here is the code within SilverlightContainerPlugin.html file:

Collapse | Copy Code

<div>
    <myobject type="application/x-silverlight-2" 
            style="display: block; text-align: center; width: 100%; height: 100%">
        <param name="source" value="___XAPFilePlaceHolder___" />
        <param name="onError" value="onSilverlightError" />
        <param name="background" value="white" />
        <param name="minRuntimeVersion" value="5.0.61118.0" />
        <param name="autoUpgrade" value="true" />
        <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style="text-decoration: none">
            <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight"
                style="border-style: none" />
        </a>
    </myobject>
</div>
<script src="../Scripts/jquery-1.8.2.js"></script>
<script type="text/javascript" data-type="script-interface">
    (function () {
        return {
            "preRender": function (preRenderArgs) {

                // get original html of the plugin
                var originalHtml = this.getDownloadedHtml()

                // replace "myobject" string with "object" and 
                // ___XAPFilePlaceHolder___ with the Silverlight app url parameter.
                var modifiedHtml = originalHtml.replace(/myobject/gi, "object").replace("___XAPFilePlaceHolder___", preRenderArgs.slAppUrl);

                // replace the HTML code of the plugin
                this.setDownloadedHtml(modifiedHtml);
            },
            "postRender": function () {
                var args = this.postRenderArguments;

                var slContainerDiv = this.currentDOM.find(".slContainerDiv");

                // position the plugin
                if (args) {
                    slContainerDiv.css("margin-top", args.marginTop);
                    slContainerDiv.css("margin-bottom", args.marginBottom);
                    slContainerDiv.css("width", args.width);
                    slContainerDiv.css("height", args.height);
                }
            },
        }
    })();
</script>

Here is how the plugin is inserted within the main module:

Collapse | Copy Code

bpf.cmpst.getPlugin(
    "SilverlightContainerPlugin.html",
    this,
    "#AWebProsLogo",
    compositionReady,
    {   // post-render args
        marginTop: "auto",
        marginBottom: "auto",
        width: "150px",
        height: "150px"
    },
    {   // pre-render args
        slAppUrl: "../ClientBin/AnimatedBanner.xap"
    }
);

This plugin is not part of BPF library (which consists only of JavaScript files) but  it can be very useful and as such it is published on  github.com/npolyak/bpf/tree/master/BPF/UsefulBPFPlugins

SPA Server Communications Using ASP.NET MVC

Here we show how SPA can communicate with the ASP.NET MVC server. Unlike the previous two  sections, this section does not contain anything new – it is simply a tutorial providing  a number of different examples of SPA communicating with the server.

Simple GET Request Sample Returning String from the Server

As was mentioned in Introduction, once the SPA is running, it should only load string or JSON data for the application and not the HTML code. A very simple example of an SPA sending and getting some string data from an ASP server can be found under SPAServerStringCommunications solution.

To start the solution, right mouse button click on Index.html file and choose “View in Browser”.  Here is how the application looks after it is started:

After you enter your name into the editable area and click “Get Server String” button  the browser will send your name to the server and receive a string “Hello <yourname>” from the server and display above the button in red:

SPAServerStringCommunications project was created as ASP.NET MVC 4 empty project. After the project was created, I removed Model and Views folders and added a “Hello” controller to the Controllers folder. I also removed all the scripts from the Scripts folder and installed JQuery as a NuGet package.

HelloControler contains only one method GetHelloMessage that takes name argument and returns string "Hello" + name wrapped in Json function:

Collapse | Copy Code

public ActionResult GetHelloMessage(string name)
{
    // AllowGet flag states that the method can be accessed
    // by GET HTTP request.
    return Json("Hello " + name, JsonRequestBehavior.AllowGet);
}

In this case Json function simply wraps a string and so, the string is returned to the server.

The relative URL to GetHelloMessage function is obtained by concatenating the controller name, forward slash and the function name: “/hello/gethellomessage”.

The project’s HTML/JavaScript client is located within Index.html file. Here is the HTML part of the client code:

Collapse | Copy Code

<body>
    <div>Enter name</div>

    <!-- name input -->
    <input id="nameInput" type="text" name="value" style="width:200px" />

    <!-- div to display the text returning from the server -->
    <div id="serverText" style="min-height:50px;color:red;margin-top:10px"></div>

    <!-- button to trigger communication with the server -->
    <button id="getHelloStringButton">Get Server String</button>
</body>

And here is the JavaScript:

Collapse | Copy Code

    $(document).ready(function () {
        $("#getHelloStringButton").click(function () { // on button click

            // get name value
            var name = nameInput.value;

            // send query string to the server.
            // /hello/gethellomessag is the relative url
            // second argument is the query string
            // 3rd argument is the function called on successful reply from the server
            $.get("/hello/gethellomessage", "name=" + name, function (returnedMessage) {

                // write the text coming fromt he server into 
                // serverText element.
                $("#serverText").text(returnedMessage);
            });
        });
    });

JavaScript code uses JQuery’s $.get function to send a GET request to relative url “/hello/gethellomessage” and  to call a function to  insert whatever come from the server into serverText element.  The structure of the query (which is part of the GET request from the client) is “name=<value-that-you’ve-entered>”. The name within the query will map into name argument of the controller function  and the value will become the value of the name argument of the controller function, so no extra parsing is necessary on the server side.

In general, when a GET query has multiple arguments, the query should be built as  name1=<val1>&name2=<val1>... and on the server side the  controller function arguments should have the same argument names as the GET query. In that case,  parsing will happen automatically and the values of the arguments will be the same as the values within the query.

GETting a Complex Object from the Server

In the previous sample, we sent a string to the server to get a string back. SPAComplexObjectGetter project returns  a JSON object with some structure to it in response to a GET HTTP request. To run the project, open it in Visual Studio right mouse click on Index.html file in Solution Explorer and choose “View in Browser”. Here is what you will see after clicking button “Get Cinema Info”:

Unlike the previous sample, SPAComplexObjectGetter project has a non-empty Models folder with two classes in it:  Cinema and Movie. Each Movie has a Title and a Year of the release. Cinema has Name, Description and a collection of Movie objects  called Movies. Cinema‘s default constructor creates a Cinema object and populates  it with some data including two Movie objects. The purpose of this sample is to show how this cinema information can be requested by the client, transferred to it from the server in JSON format and displayed on the  client side.

“Controllers” folder contains DataController.cs file with only one method:

Collapse | Copy Code

public ActionResult GetCinema()
{
    // create a cinema object populated with data
    Cinema cinema = new Cinema();

    // send it in JSON form back to the client
    return Json(cinema, JsonRequestBehavior.AllowGet);
}

The relative URL to call method GetCinema within DataController is “/data/getcinema”.

Now let us look at the client code within Index.html file.  HTML code is very simple consisting of a div to add the cinema info to and of  a button for triggering the exchange with the server:

Collapse | Copy Code

<body>
    <div id="cinemaInfo" style="margin-bottom:20px"></div>

    <Button id="getCinemaInfoButton">Get Cinema Info</Button>
</body>

JavaScript code is more complex, but just like the code of the previous sample, it uses JQuery  function $.get to send GET request to the server and process  whatever information is returned from the server:

Collapse | Copy Code

$(document).ready(function () {
    $("#getCinemaInfoButton").click(function () { // on button click

        // send query string to the server.
        // /hello/gethellomessag is the relative url
        // second argument an empty string since our query does not have parameters
        // 3rd argument is the function called on successful reply from the server
        $.get("/data/getcinema", "", function (cinema) {

            // clear the info displayed from 
            // the previous click (if any).
            $("#cinemaInfo").contents().remove();

            // add cinema information to "cinemaInfo" div element
            $("#cinemaInfo").append("Name: " + cinema.Name);
            $("#cinemaInfo").append("<div></div>");
            $("#cinemaInfo").append("Description: " + cinema.Description);
            $("#cinemaInfo").append("<div style='margin-top:5px'></div>");
            $("#cinemaInfo").append("Movies:");
            $("#cinemaInfo").append("<div></div>");
            // add information about individual movies
            for (var idx = 0; idx < cinema.Movies.length; idx++) {
                var movie = cinema.Movies[idx];

                $("#cinemaInfo").append
                (
                    "    " +
                    "Title: " + movie.Title +
                    ",    " +
                    "year: " + movie.Year
                    );
                $("#cinemaInfo").append("<div></div>");
            }
        });
    });
});

The query part of the function $.get is empty, since  our GET request does not have any parameters.

The object returned from the server is represented by variable cinema which is an input variable to the function called on GET request success. Within that function we form the text and append it to the “cinemaInfo” div tag. The returned cinema object has fields Name and Description as well as an array of movie objects called Movies. Each movie object has Title and Year fields. In fact, the returned JSON object mimics the server side C# object of type Cinema.

You can view the JSON object returned from the server by opening a browser e.g. Chrome and  typing the URL to the controller function GetCinema: “http://localhost:29863/data/getcinema&#8221;.  You will see the returned JSON string in the browser.

POSTing Complex Data Object to the Server

GET requests presented in the two previous samples build the query as part of the URL and as such  GET requests are perfect when an object you want to send a set of names and values to the server.  When a complex JSON object needs to be transferred from the client to the server, POST request should be utilized.

In this sub-section we will consider the same Cinema model as in the previous one, only the model will be created on the client, sent to the server for modifications, returned by the server back to the client and displayed on the client.

This sub-section’s sample is located under SPA_POSTingObjectToServer solution.

The server has the same model classes: Cinema and Movie, but Cinema‘s default constructor is empty since the data is coming from the client. DataController‘s method ChangeCinemaData changes the data coming from the client by adding another movie “Anne of Planet Mars” to the collection of the movies. Then it returns the modified Cinema object back to the client.

To cover the case of the server failure, I also made the server request fail every other time.  To mark the failure, the server changes the Response‘s StatusCode and returns “serverError” as a string.  Here is the server code:

Collapse | Copy Code

static bool evenRequest = true;

// url=/data/changecinemadata
public ActionResult ChangeCinemaData(Cinema cinema)
{
    evenRequest = !evenRequest;

    // report error on every even request
    if (evenRequest)
    {
        Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;

        return Json("serverError");
    }

    // add movie "Anne of Planet Mars"  
    // to Cinema data coming from the client 
    // and return the modified Cinema data
    // back to the client
    cinema.Movies.Add
    (
        new Movie
        {
            Title = "Anne of Planet Mars",
            Year = 3000
        }
    );

    return Json(cinema);
}

Note, that the server will interpret the data coming from the client as  an object of type Cinema as long as the object has correct structure.

The client code is located in Index.html file. HTML consist of two div tags – one for the visual representation of the original Cinema object – the other one for holding  the visual representation of the modified Cinema object returned from the server. There is also a button placed between them to trigger the exchange with the server.  The visual representation of the server reply is colored in red.

Collapse | Copy Code

<body>
    <!-- Here we place the original cinema data-->
    <div id="originalCinemaInfo" style="margin-bottom:20px"></div>

    <!-- clicking this button sends the cinema object to the server
         and places the result returning from the server under 
         serverCinemaInfo tag -->
    <Button id="changeCinemaInfoFromServerButton">Change Cinema Info via Server</Button>

    <div style="color:blue;margin-top:20px">Reply from the Server:</div>

    <!-- here we create a visual representation for Cinema object 
         coming from the server -->
    <div id="serverCinemaInfo" style="margin-bottom:20px;color:Red">

    </div>
</body>

Here is the JavaScript code:

Collapse | Copy Code

 
$(document).ready(function () {
    // we create a Cinema object on the client
    var cinema = {
        Name: "Mohawk Mall Cinema",
        Description: "An OK Cinema",

        Movies: [
            {
                Title: "Anne of Green Gables",
                Year: 1985
            },
            {
                Title: "Anne of Avonlea",
                Year: 1987
            }
        ]
    };

    // display the visual representation of the original 
    // cinema object
    displayCinemaInfo($("#originalCinemaInfo"), cinema);

    var cinemaJsonString = JSON.stringify(cinema);

    $("#changeCinemaInfoButton").click(function () {
        $.ajax({
            type: "POST",
            dataType: "json",
            contentType: "application/json; charset=utf-8;",
            url: "/data/changecinemadata",
            data: cinemaJsonString,
            success: function (changedCinemaFromServer) {

                // display the visual representation of the server modified 
                // cinema object
                displayCinemaInfo($("#serverCinemaInfo"), changedCinemaFromServer);
            },
            error: function (resultFromServer) {

                // clear the previous contet of serverCinemaInfo element
                $("#serverCinemaInfo").contents().remove();

                // display the error message
                $("#serverCinemaInfo").append("Server Error");
            }
        });
    });
});

We use generic $.ajax method to send a POST request to the server. This method allows us to also specify the function to be called in case of a server error as well as the content type for the request.

The data we send within the message body is our Cinema JSON object turned into string by JSON.stringify function. Some older browsers  still do not support this function and because of that, the reference to json2.min.js  file was added. This file came from NuGet installation of the json2 package.

Here is how the SPA looks after successful reply from the server:

and here is how it looks in case of failure:

 

Summary

This article talks about the Single Page Applications (SPAs). We define the SPA   and present numerous SPA samples.  All the information and functionality within the article is something I wished I knew and had several months  ago when I just started building the SPAs.

This article introduces a new JavaScript library called BPF (Browser Presentation Foundation). This library is used for two   purposes:

  • Navigation – enabling to navigate your SPA using browser URLs and navigation buttons.
  • Composition – showing how one can use BPF library to compose the SPA from different HTML pages    on the client.

Eventually, I hope that the BPF library will include a lot of other functionality.

Thank you

 

This free website was made using Yola.

No HTML skills required. Build your website in minutes.

Go to www.yola.com and sign up today!

Make a free website with Yola