The Widget Factory

Total Page:16

File Type:pdf, Size:1020Kb

The Widget Factory The Widget Factory Version 1.8 of jQuery UI split the functionality that allows widgets to be easily created into a separate and standalone utility file. This is the jquery.ui.widget. js file and we can use it to create our very own jQuery UI plugins with ease. Like jQuery itself, which provides the fn.extend() method for easily creating plugins, jQuery UI also provides mechanisms to make plugin creation easier and to ensure that the common API functionality is retained in new plugins. In this chapter, we will cover the following topics: • The benefits of using the Widget Factory to write plugins • Creating and invoking widget methods • Resetting a widget • Creating an example calculator widget • Adding options to our example widget • Making widgets themeable • Supporting the common API methods • Adding methods and responding to events in our widget • Using our widget in a web page Introducing the Widget Factory If you've spent some time working with jQuery, you will no doubt have created a plugin of some description, or have used ones already created by others, as part of developing with the library. The recent jQuery plugins are stateless, where the extent of the interaction is limited to us calling them on an element. In most cases, this works perfectly well, but there's a large set of functionality that doesn't fit into the basic plugin pattern. The Widget Factory To help fill this gap, jQuery UI has implemented a more advanced plugin system. The new system manages state, allows multiple functions to be exposed via a single widget, and provides various extension points. This system is called the Widget Factory and is exposed as jQuery.widget as part of jQuery UI. Reasons for using the Widget Factory When writing jQuery plugins, we would normally add or override a property or method within jQuery.prototype (or $.fn, as it is more commonly written), and follow some conventions such as returning this, to allow the plugin to be chained with others within our code. So what is the Widget Factory all about, and why should we use something that is hundreds of lines long? There are two main reasons why we should use the factory: • Eliminate the need to produce a lot of boilerplate code for the plugin: In most cases, jQuery plugins are stateless; they perform a single action on an element and don't need to be preconfigured. In these instances, we would normally extend jQuery's prototype. If a plugin is stateful, it requires code to manage state and react to changes. The Widget Factory is a means to help the abstract code for common tasks such as creating or destroying widgets into a clear, consistent format that can be used across all jQuery UI plugins. • Produce a consistent API: The Widget Factory creates a common standard framework that you use to create and destroy widgets, get and set options, and invoke methods, of which a large part of this is already implemented by the Factory. Using a defined standard makes it easier for others to use your widgets. In summary, the Widget Factory also provides a number of benefits that we can utilize when developing widgets. These include the following: • We can create our own namespace rather than using the default of ui, which is not a good practice (jQuery.al) • The widget can use its own class (jQuery.al.filterable.prototype) and extend the existing jQuery prototype (jQuery.fn.filterable) • We can create our default settings, then merge-in any user-defined settings • We can use the .data() method to store plugin instance in .data() • Methods are accessible via use of string—plugin( "foo" ) or directly .foo() • The factory helps prevent against multiple instantiation of the same widget [ 2 ] Chapter 15 • The structure for implementing creation, destruction, and changes within the plugin has been written as a series of events, so we can break the widget code into a series of smaller functions, making it easier to manage • We can easily expose callbacks using the ._trigger method such as _trigger( "event" ) • We can use this to maintain proper scoping of elements throughout the plugin Let's now take a look at how to create the basic skeleton of your widget file, which we will use later in this chapter to create an example calculator widget. Creating a skeleton plugin When using the Widget Factory to create widgets within jQuery UI, you will notice that there are a number of common methods that will be used in the code. Let's take a look at each of them in more detail. We begin with creating the namespace for our widget; this should use a custom name in the format of <custom-ui-name>.<name-of-widget>. The namespace will be created automatically, if it doesn't already exist. We also need to set the options that will be available to our end users, and which they can use to change the widget's configuration: ( function($,undefined) { $.widget( "al.progressbar", { // These options will be used as defaults options: { className : "" }, Next comes the initialization method for the widget; here is where we set up the widget when it is called from within our web pages: _create: function() { ... }, We then need to implement our various methods that users can then call upon when using the widget in their code: filter: function() { ... }, [ 3 ] The Widget Factory There will be methods that we need to implement in our widget, the scope of which is only intended to be within the widget itself and not for general consumption. We can implement these in the same manner as the public methods, but with the addition of the underscore before the name to denote a private method: _hover: function() { ... }, Unless our widget only performs one operation or doesn't need to allow the user to change its configuration, we will very likely need to configure the widget with some options. We will have already created the array of options at the beginning of the plugin, we now need to respond to those option changes and process any requests. We start with _SetOptions, which is called anytime the option() method is used: _setOptions: function (options) { this._superApply(arguments); }, This in turn calls _SetOption, which processes each option change before calling the parent function: _setOption: function( key, value ) { ... return this._superApply( arguments ); } Finally we need to call _destroy to ensure our widget is reset back to the default, before either reinitializing it on screen or removing it completely: _destroy: function() { return this._super(); }, }); })(jQuery); Setting options in a widget Throughout this book, we've already seen that each of the different components in the library has a series of options that control widget features, the Widget Factory is no different. It has three base options you can use to configure the appearance of the widget; these are in addition to any that you add as custom options to your widget. [ 4 ] Chapter 15 The available options to configure behaviors are shown in the following table: Option Default value Use disabled false Disables the widget if set to true hide null Sets if or how to animate the hiding of the widget—it can accept boolean, string, number, or object as input show null Sets if or how to animate the displaying of the widget—it can accept boolean, string, number, or object as input Setting options on initialization In addition, we can add our own options to the widget, in a similar fashion to that you might use for creating jQuery plugins. It's good practice to expose the defaults for each option, so that users can change them when configuring your plugin. We can then merge these into the standard options that are exposed by the widget, before destroying them when we are finished with the widget. A common pattern in jQuery plugins looks like this: $.fn.plugin = function( options ) { options = $.extend( {}, $.fn.plugin.defaults, options ); // Plugin logic goes here. }; $.fn.plugin.defaults = { param1: "foo", param2: "bar", param3: "baz" }; The Widget Factory provides this functionality and takes it a bit further: $.widget( "al.plugin", { // Default options options: { param1: "test", param2: "foo", param3: "sample" }, _create: function() { [ 5 ] The Widget Factory // Options are already merged and stored in this.options // Plugin logic goes here. } }); Once we've set our options, we can then respond to changes in any of the options; we'll see how in the Watching out for changes section later in this chapter. Creating the base widget Now that we've set our initial options, we need to initiate our plugin. This is done using the _create() method. Here, we would call any methods that are needed to create our widget on screen and configure default values or settings for our widget: Option Default value Use _create() jQuery This is the widget's constructor method, which we use to initiate our widget. It doesn't require any parameters, but this.element and this.options are already set. Setting widget methods In a similar fashion to other components in the library, the Widget Factory exposes a number of other methods that we can use when creating our widgets, in addition to the core methods of destroy, disable, enable, option, and widget. Let's take a look at the some of the methods available, which are listed in the following table: Method Returns Use _delay Number Invokes the specified functionality after a specified delay. _destroy jQuery Cleans up all common data, events, and so on, and then delegates to _destroy() for custom, widget-specific, clean-up. _focusable jQuery Sets up the specified element to apply the ui-state-focus class on focus.
Recommended publications
  • Web Application Development Using TCL/Apache Rivet and Javascript Anne-Leslie Dean, Senior Software Developer, Flightaware Prese
    Web Application Development Using TCL/Apache Rivet and JavaScript Anne-Leslie Dean, Senior Software Developer, FlightAware Presented: 25th Annual TCL/Tk Conference, Oct 15-19, 2018 Introduction Modern Web applications rival native applications in user experience. This is accomplished by manipulating the Web document dynamically in the client browser environment. There are a many choices of scripting (language) environments a developer may choose to use on the web server: PHP, Python, Ruby, TCL etc. But on the client side, the JavaScript environment is the standard for programmatic control of the Web application. Apache Rivet provides a server environment to build Web applications using TCL. This case study will demonstrate the application of fundamental software design principles such as separation of concerns, abstraction, and encapsulation in a TCL/Apache Rivet environment with integrated JavaScript. The basic structure of the Rivet script will distinguish content management from presentation and will visibly identify a clear interface between the TCL/Apache Rivet and the JavaScript environments. Each step of the case study will conclude with an analysis of the software development principles being applied. Case Study Step 1: Framing Out The Rivet Script The distinguishing architectural feature of modern Web applications boils down to a simple model: a document template rendered against an abstracted data model. The code concerned with managing the abstracted data model is commonly referred to as content management. The code concerned with describing the document template is commonly referred to as presentation. The basic structure of an Apache Rivet script should always reinforce this Web application architectural distinction. This can be accomplished by applying the software principle of separation of concerns with respect to content management and presentation.
    [Show full text]
  • THE FUTURE of SCREENS from James Stanton a Little Bit About Me
    THE FUTURE OF SCREENS From james stanton A little bit about me. Hi I am James (Mckenzie) Stanton Thinker / Designer / Engineer / Director / Executive / Artist / Human / Practitioner / Gardner / Builder / and much more... Born in Essex, United Kingdom and survived a few hair raising moments and learnt digital from the ground up. Ok enough of the pleasantries I have been working in the design field since 1999 from the Falmouth School of Art and onwards to the RCA, and many companies. Ok. less about me and more about what I have seen… Today we are going to cover - SCREENS CONCEPTS - DIGITAL TRANSFORMATION - WHY ASSETS LIBRARIES - CODE LIBRARIES - COST EFFECTIVE SOLUTION FOR IMPLEMENTATION I know, I know, I know. That's all good and well, but what does this all mean to a company like mine? We are about to see a massive change in consumer behavior so let's get ready. DIGITAL TRANSFORMATION AS A USP Getting this correct will change your company forever. DIGITAL TRANSFORMATION USP-01 Digital transformation (DT) – the use of technology to radically improve performance or reach of enterprises – is becoming a hot topic for companies across the globe. VERY DIGITAL CHANGING NOT VERY DIGITAL DIGITAL TRANSFORMATION USP-02 Companies face common pressures from customers, employees and competitors to begin or speed up their digital transformation. However they are transforming at different paces with different results. VERY DIGITAL CHANGING NOT VERY DIGITAL DIGITAL TRANSFORMATION USP-03 Successful digital transformation comes not from implementing new technologies but from transforming your organisation to take advantage of the possibilities that new technologies provide.
    [Show full text]
  • Tripwire Ip360 9.0 License Agreements
    TRIPWIRE® IP360 TRIPWIRE IP360 9.0 LICENSE AGREEMENTS FOUNDATIONAL CONTROLS FOR SECURITY, COMPLIANCE & IT OPERATIONS © 2001-2018 Tripwire, Inc. All rights reserved. Tripwire is a registered trademark of Tripwire, Inc. Other brand or product names may be trademarks or registered trademarks of their respective companies or organizations. Contents of this document are subject to change without notice. Both this document and the software described in it are licensed subject to Tripwire’s End User License Agreement located at https://www.tripwire.com/terms, unless a valid license agreement has been signed by your organization and an authorized representative of Tripwire. This document contains Tripwire confidential information and may be used or copied only in accordance with the terms of such license. This product may be protected by one or more patents. For further information, please visit: https://www.tripwire.com/company/patents. Tripwire software may contain or be delivered with third-party software components. The license agreements and notices for the third-party components are available at: https://www.tripwire.com/terms. Tripwire, Inc. One Main Place 101 SW Main St., Suite 1500 Portland, OR 97204 US Toll-free: 1.800.TRIPWIRE main: 1.503.276.7500 fax: 1.503.223.0182 https://www.tripwire.com [email protected] TW 1190-04 Contents License Agreements 4 Academic Free License ("AFL") 5 Apache License V2.0 (ASL 2.0) 9 BSD 20 Boost 28 CDDLv1.1 29 EPLv1 30 FreeType License 31 GNU General Public License V2 34 GNU General Public License V3 45 IBM 57 ISC 62 JasPer 63 Lesser General Public License V2 65 LibTiff 76 MIT 77 MPLv1.1 83 MPLv2 92 OpenLDAP 98 OpenSSL 99 PostgreSQL 102 Public Domain 104 Python 108 TCL 110 Vim 111 wxWidgets 113 Zlib 114 Contact Information 115 Tripwire IP360 9.0 License Agreements 3 Contents License Agreements This document contains licensing information relating to Tripwire's use of free and open-source software with or within the Tripwire IP360 product (collectively, "FOSS").
    [Show full text]
  • Eddie Corrigall NOTE Last Updated on 2015-12-17
    Eddie Corrigall NOTE Last updated on 2015-12-17 CONTACT 1-226-606-2477 Yonge and Eglinton, Toronto, ON [email protected] @ LinkedIn, @ GitHub SUMARY I graduated from the University of Waterloo in 2014 with Honours Bachelor of Computer Science (BCS). I’ve learned a lot about the Ad Tech Industry this year while working at Eyereturn Marketing Inc. I used Apache Hadoop to operate on and house a lot of data and aggregate the important info into SQL servers for applications. Now I’m looking to be part of a team, have a well defined role, and ownership over a product or service. My long-term goal is to focus on more traditional software development that will include a release cycle and teamwork. What I’ve worked on in the past • Mining big data using Apache Hadoop and Apache PigLatin Data analytics using Python Pandas, NumPy, SciKit Learn • Real-time analytic software using C# Windows Presentation Foundation (WPF) • Crowd sourcing application using Amazon Web Services (AWS) Mechanical Turk (mTurk) • Custom implementation of I2C bus and LPC bus in C for an Embedded security platform • Web portal written in SQL, PHP, JavaScript for team knowledge tracking application Side Projects I have many side projects, some of which are farther along than others. These projects get me involved in technologies to strengthen my abilities and satisfy my ambition for knowledge. If you check out my GitHub account, there are plenty of working examples of my development abilities, so I encourage you to explore! What I’m looking to do next My internships at the University of Waterloo allowed me to pursue development opportunities within 1 many unique industries.
    [Show full text]
  • Preview Jqueryui Tutorial (PDF Version)
    JQueryUI About the Tutorial JqueryUI is the most popular front end frameworks currently. It is sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development. It uses HTML, CSS and Javascript. This tutorial will teach you basics of JqueryUI Framework, which you can use to create complex web applications GUI with ease. This Tutorial is divided into sections such as JqueryUI Basic Structure, JqueryUI CSS, JqueryUI Layout Components and JqueryUI Plugins. Each of these sections contain related topics with simple and useful examples. Audience This tutorial has been prepared for anyone who has a basic knowledge of HTML and CSS and has an urge to develop websites. After completing this tutorial, you will find yourself at a moderate level of expertise in developing web projects using Twitter JqueryUI. Prerequisites Before you start proceeding with this tutorial, I'm making an assumption that you are already aware about basics of HTML and CSS. If you are not well aware of these concepts, then I will suggest to go through our short tutorial on HTML Tutorial and CSS Tutorial. Disclaimer & Copyright Copyright 2015 by Tutorials Point (I) Pvt. Ltd. All the content and graphics published in this e-book are the property of Tutorials Point (I) Pvt. Ltd. The user of this e-book is prohibited to reuse, retain, copy, distribute, or republish any contents or a part of contents of this e-book in any manner without written consent of the publisher. We strive to update the contents of our website and tutorials as timely and as precisely as possible, however, the contents may contain inaccuracies or errors.
    [Show full text]
  • On Getting Rid of Javascript
    On Getting Rid of JavaScript Alessandro Vermeulen (3242919) Department of Computer Science, Utrecht University February 23, 2012 1 Introduction Haskell is a beautiful and powerful language. Its functional background and strong type system makes it particularly useful for programming complicated computations and programs. Although Haskell is intrinsically well suited to program calculations it is, from a programmer's standpoint, harder to write a application with a native GUI in it. Currently there are only two options when writing a GUI: either use wxHaskell or GTKHaskell. Both bindings to the GUI suffer however from being not well maintained and in being difficult to set up. One solution to work around needing a complicated binding to a GUI library is to create a website. This website will look and work (virtually) the same across multiple operating systems and browsers. It is then the browser that will take care of providing the correct, operating specific, look and feel to the website. Traditionally websites are `programmed' in HTML and JavaScript. This project was all about showcasing the UHC's JavaScript-backend. The idea is to get rid of the necessity of having to write your own JavaScript. JavaScript is a language that contains idiosyncrasies, such as the changing of the scope of this. On top of that although it is an imperative, object-oriented, programming lan- guage with support for first class functions, it does not contain convenient ways of partial application, and lazy evaluation. All essential elements of Haskell. In addition it is not a statically typed language so mistakes are easy to make.
    [Show full text]
  • Choosing the Best Javascript Framework
    Choosing the Best JavaScript Framework Andy Gup, Esri US Raul Jimenez, Esri ES Frameworks, frameworks, … Do I even need a framework?? Has.jsRaphael The Boiler BootstrapLess+ DojoWirefy Foundation 3 SenchaTitan Susy Skeleton Ingrid jQuery Less Phonegap X X 1991 2012 ECMA 5.1 ECMA 2015 June 2011 June 2015 JavaScript Frameworks & Libraries: Timeline MooTools Kendo Polymer 05/2014 script.aculo.us 09/2006 AngularJS UI 06/2005 2009 04/2014 Kartograph Ionic 08/2013 Phonegap jQuery 2013 2009 08/2006 Backbone Ember.js 10/2013 JavaScriptMVC Knockout 12/2011 YUI 05/2008 02/2006 7/2010 CMV 02/2013 Web Bootstrap AppBuilder Titanium Prototype 04/2011 07/2014 12/2008 2005 ExtJS Ractive 12/2007 08/2013 React native jQuery React.js 03/2015 Dojo Mobile 2013 08/2005 10/2010 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 Event-driven One-Page Discontinued Hybrid Geospatial Trends: Interest over time 2005 - 2007 2007 - 2012 2004 - 2012 Your Considerations • New project or expanding existing project? • Your project size (small, medium, large)? • Do you have existing build system? • Do you have existing frameworks? • Your teams skill sets? • Your requirements? Learning curve Evaluating a framework • Framework 3rd party sponsorship • Major version changes • Documentation • Stackoverflow questions Evaluating a framework Angular.js Mono Evaluating a framework Latest commit … Oct 6, 2011!!! Evaluating a framework Number of: • Closed issues • Open issues • Open pull requests • Contributors Evaluating a framework • Trendiness (cool factor) vs Stable/Secure
    [Show full text]
  • UI Programming
    UI Programming (part of this content is based on previous classes from Anastasia, S. Huot, M. Beaudouin-Lafon, N.Roussel, O.Chapuis) Assignment 1 is out! Design and implement an interactive tool for creating the layout of comic strips https://www.lri.fr/~fanis/teaching/ISI2014/assignments/ass1/ Graphical interfaces GUIs: input is specified w.r.t. output Input peripherals specify commands at specific locations on the screen (pointing), where specific objects are drown by the system. Familiar behavior from physical world WIMP interfaces WIMP: Window, Icons, Menus and Pointing Presentation ! Windows, icons and other graphical objects Interaction ! Menus, dialog boxes, text input fields, etc Input ! pointing, selection, ink/path Perception-action loop ! feedback Software layers Application Applications/Communication (MacApp) Builders, Java Swing, JavaFX, Qt (C++), Interface Tools & Toolkits GTK+, MFC, Cocoa Graphics Library GDI+, Quartz, GTK+/Xlib, OpenGL Windowing System X Windows (+KDE or GNU) Input/Output Operating System Windows, Mac OS, Unix, Linux, Android, iOS, WindowsCE Software layers Application Interface Tools & Toolkits Graphics Library Windowing System Input/Output Operating System Input/output peripherals Input: where we give commands Output: where the system shows information & reveals its state Interactivity vs. computing Closed systems (computation): ! read input, compute, produce result ! final state (end of computation) Open systems (interaction): ! events/changes caused by environment ! infinite loop, non-deterministic
    [Show full text]
  • Technical Expertise
    www.ultantechnologies.com Technical Expertise Subject: Ultan Technologies Technical Expertise Author: Cathal Brady Date Published: 01/03/2016 Version Number: Version 1 www.ultantechnologies.com Contents 1 INTRODUCTION ..................................................................................................................... 1 2 .NET ....................................................................................................................................... 1 3 DATABASES ........................................................................................................................... 2 4 BIG DATA ............................................................................................................................... 2 5 JAVA ...................................................................................................................................... 3 6 PHP, RUBY, PYTHON .............................................................................................................. 3 7 FRONT END............................................................................................................................ 4 8 3RD PARTY INTEGRATION, APIs, PLUGINS ............................................................................. 4 9 CONTINUOUS INTEGRATION / BUILD AUTOMATION / VERSION CONTROL .......................... 4 10 MOBILE DEVELOPMENT ........................................................................................................ 5 11 CRM CUSTOMISATION .........................................................................................................
    [Show full text]
  • Licensing Notes for Oracle's Peopletools 8.53
    Licensing Notes Licensing Notes for Oracle’s PeopleTools 8.53 January 2014 Licensing Notes for Oracle’s PeopleTools 8.53 Copyright © 2014, Oracle and/or its affiliates. All rights reserved. License Restrictions Warranty/Consequential Damages Disclaimer This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited. Warranty Disclaimer The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing. Restricted Rights Notice If this software or related documentation is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable: U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are “commercial computer software” or “commercial technical data” pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007).
    [Show full text]
  • View Component of Web-Based IDE in Cakephp
    View Component of Web-based IDE in CakePHP A Writing Project Presented to The Faculty of the Department of Computer Science San José State University In Partial Fulfillment of the Requirements for the Degree Master of Science By Swathi Vegesna Spring 2010 Abstract The aim of the project is to build the view component of a Web-based IDE that enables users to create XHTML pages and link up the tags with the Controller files by only using drag and drop mechanism in cakePHP. This is the view component of the MVC based Web-based IDE, which will connect the Controllers and View components. This project will enhance these elements by making them dynamic which is achieved by connecting to the Controller components. This IDE helps the users to create the dynamic web pages even without good knowledge of XHTML and server side scripting languages. The user will be able to include all kinds of elements only with drag and drop mechanism and develop the whole web page. Table of Contents 1. Introduction ...................................................................................................................................4 2. Experiments with cakePHP ..............................................................................................................5 2.1 Motivation ................................................................................................................................5 2.2 Goal .........................................................................................................................................5
    [Show full text]
  • Context Scope Perspective Cics Js/Server V2
    CONTEXT SCOPE PERSPECTIVE CICS JS/SERVER V2 The Business Issue Modern business applications demand user interfaces with sophisticated features. Many such features are provided by web browsers that communicate with server technology to access corporate data and drive business processes. In many large corporations, the server of choice with which the browser communicates is the IBM mainframe. Web browsers support the JavaScript scripting language which can be used for many purposes including the creation of visual effects and dynamically create or alter the web page contents. Over time, JavaScript Libraries and Toolkits have emerged (many in the Open Source arena) that make the creation of Web documents much easier than attempting to use native JavaScript in a bespoke manner. Javascript tools such as the Dojo Toolkit, JQuery, JQuery UI, MooTools, YUI Library (and others) enable the rapid development of browser based user interface functions. These tools are themselves composed of JavaScript files that have to be served to the browser. It is sensible to exert control over what is served to the browser as part of corporate business applications. CICS JS/Server serves a number of the most popular JavaScript Libraries and Toolkits to web browsers from CICS on the mainframe. For more information about the Dojo Toolkit, visit http://dojotoolkit.org/ For more information about JQuery, visit http://jquery.com/ For more information about JQuery UI, visit http://jqueryui.com/ For more information about MooTools, visit http://mootools.net/ For more information about YUI Library, visit http://yuilibrary.com/ For a complete list of the JavaScript Libraries and Toolkits supported and the versions included in CICS JS/Server V2, visit our website: www.plexspy.com NOTE: CICS JS/Server V2 also allows for bespoke content to be defined and served under its control.
    [Show full text]