Blog

Labels
AJAX(112) App Studio(7) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(177) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(183) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(2) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Friday, July 30, 2021PrintSubscribe
Drag, Cut, Copy, and Paste Your Data

Clipboard is an indispensable tool if you are composing an email, creating a document, or writing code. “Cut and paste” helps us to rearrange our thoughts. “Copy and paste” comes handy when we are out of ideas.

An input field in a custom business app provides instant access to the system clipboard when editing a value. A selected fragment of text can be dragged and dropped into a new position. App users work with the collections of data items. A data item represents a group of related fields. Wouldn't it be great to take advantage of the clipboard and drag & drop to copy or move the items between or within the data collections?

Clipboard and Drag & Drop With Structured Data

The clipboard commands and drag & drop can benefit a business app when applied to the structured data. Consider the Order Management Dashboard presented below. 

You can see the end user dragging the product from the menu and dropping it directly on the list of details of the selected order. The product Boston Crab Meat is semi-transparent in the menu of 77 products while it is being dragged. The “drop” frame outlines the Order Details as a target accepting the product. The mouse pointer is displayed as the “copy” arrow. The tooltip with the name of the dragged item is shown next to the pointer.

 

The result of the product “drop” is shown next. The product is no longer visible in the menu of 76 products presented on the right-hand side of the dashboard. The dropped product is now linked to the selected order. It is visible in the list of details. The “drop” frame has disappeared.

The following screenshot shows the state of the dashboard just moments after the user has started dragging the product. The list of details is still empty. The mouse pointer is a no-drop icon indicating that the drop is not accepted in the current position. The “drop” frame will appear when the pointer is over the list of details.

 

 
The end user can select the Copy command from the context menu of a product. The “drag indicator” doubles as the “more” menu when tapped or clicked. The command is also visible on the toolbar of the Products grid.

 
Here is the result of the Paste command executed three times on the Order Details. The product Aniseed Syrup has disappeared from the menu of products, which is now reduced to 75 items. The product is visible in the list of order details with the quantity set to 3. The Paste command on the toolbar of the details shows the tooltip with the description of the copied item and its source.

 
This application also enables the drag & drop capabilities for the Shippers. It may be useful when implementing the rearranging of items. 

The “drag indicator” icon is shown in each row next to the values in the first column of the grid. It replaces the standard “more” icon. The mouse pointer switches to the “grab” style when hovering over the icon. It prompts the end user that the corresponding item can be dragged.


Dragging of the item will switch the pointer to “no-drop” when dragging over the targets that do not accept the drop. The dragged item is semi-transparent and the tooltip next to the system pointer explains what is being dragged.


The list of shippers is configured to accept the drop of its own items. The mouse pointer style is “move” when hovering over the items in the same list. 


Dragging to the other user interface elements of the Shippers grid will cause the entire list to become the “drop” target.

 

Cut/Copy/Paste and Drag & Drop in Touch UI

Touch UI provides the built-in data clipboard with the persistent state. System actions Cut/Copy/Paste and item dragging is enabled in the app with the simple tagging of the corresponding data views. Commands CutPaste, CopyPaste, and DragDrop are automatically executed by the framework in response to the user actions. Developers can create custom JavaScript, SQL, and Code business rules responding to the commands. The command argument indicates the name of the source data controller. Developers have access to the target row of the command and the row that was cut, copied, or dragged. The source row fields are prefixed with the name of the source data controller. There is no built-in processing for the commands and their interpretation and security is left up to the application developers. If multiple items were copied, cut, or dropped, then the corresponding command is executed for each item in the context of the transaction. The successful execution of the command for all items will result in the automatic commit. An error will rollback the effect of CutPaste, CopyPaste, and DragDrop for all items. Clipboard objects created with Cut and Copy commands are available to all pages of the application. This makes it possible to offer a comprehensive clipboard experience with the structured data. The clipboard contents remain persisted until the next Cut/Copy is executed by the user. This enables pasting the same data multiple times. Developers may opt to clear the clipboard after each CutPaste or CopyPaste command when needed. The unique unified data processing of Touch UI allows creating a consistent clipboard and drag & drop experience for the structured data. Let’s learn how to build this Order Management Dashboard.
 

Dashboard Configuration

Begin by creating a new project with Code On Time. Connect to the instance of the Northwind database. Create the following models with the default settings: Orders, Customers, Employees, Shippers, OrderDetails, Categories, Products, and Suppliers. Optionally configure the orders to sort by dates with the most recent ones at the top. Activate the project designer and create the new custom data controller with the name Dashboard1. This controller is not based on any data model. Select Orders, OrderDetails, and Products controllers with Ctrl+click and choose Copy in the context menu of either one of them. Right-click the Dashboard1 controller and choose Paste. This will create the corresponding DataView fields. Set the Filter Source of OrderDetails field to Orders and Filter Field #1 to Order ID. This will enable the master-detail relationship between the Orders and the Details in the dashboard. If the order is selected, then the details will be filtered to show the linked items. Set the Filter Source property of the Products field to Orders but do not select any filter fields. The product menu will behave as any other detail in the master-detail relationship. It will hide if there is no order selected in the dashboard. It will show up and refresh when the order selection has changed. The server-side code will also have access to the primary key of the order. Create the view form1, set its type to Form, the label to Order Manager, and tag it as material-icon-category. Create two categories in the form1. Set the flow of both categories to New Column. Rename the categories by selecting the corresponding command in the context menu to orders and products. Drag the Orders and OrderDetails fields to the first category. Set the Page Size of the Orders data field to 3. Also set its Auto Highlight First Row to Yes. This will ensure that only the three most recent orders are visible with the first one selected when the dashboard is loaded. Next set the Page Size of the OrderDetails data field to 25. Drag the Products field to the second category and set the Page Size of the created data field to 7. The Dashboard1 data controller will look like this in the Project Designer on the Controllers tab.
 


Now it is time to configure the Cut/Copy/Paste and Drag & Drop. Tag the Dashboard1 / views / form1 / orders / OrderDetails data field as shown below to enable the pasting and dropping of Products into Order Details

item-paste-Products item-drop-Products
Tag the Dashboard1 / views / form1 / products / Products data field with the following tags to enable Cut, Copy, and dragging of Products:

item-cut item-copy item-drag myapp-product-menu
The custom tag myapp-product-menu will be used later when filtering the product menu. Create the page called Dashboard and drag it after the Home page. Copy and paste the data controller Dashboard1 onto the page. Set its property Show Action Buttons to None. Enter Wide in the Icon / Custom Style property to remove the sidebar on the page. The visual configuration of the dashboard is now complete!
 

Implementing Paste and Drop

Commands CopyPaste, CutPaste, and DragDrop are executed on the OrderDetails data controller when the user pastes the previously cut or copied product or drags and drops one from the product menu onto the view. We will create a single SQL business rule to handle all of these situations. Our objective is to insert or update a record in the Order Details table.


 
Create a new SQL business rule in the OrderDetails data controller. Set its phase to Execute and its Command Name to CutPaste|CopyPaste|DragDrop regular expression. Enter the following script:
 


The business rule is triggered when the command with the name matching the regular expression is detected by the app framework on the server. 

The SQL script will attempt to increment the Quantity column of the existing [Order Details] row with the product ID matching the parameter @Products_ProductID. This parameter is supplied by Touch UI and its value is set to the dragged, cut, or copied ProductID. Note that it is possible to access any other property of the product by specifying the name of the data controller as a prefix separated with the underscore character from the field name.

Touch UI also supplies the value of the parameter @OrderID. It is set to the value of the OrderDetails.OrderID field in the “drop” or “paste” target item. If the target is the entire Order Details view then the field values are set to NULL with the exception of the fields specified in the Filter Fields property. The values of these fields are borrowed from the selected master row. The business rule has the value of the selected OrderID regardless of the drop or paste target.

If no rows have changed after UPDATE then the SQL business rule will INSERT an order detail with the same product and order identifiers with the quantity of 1.

Filtering Items in the Product Menu 

Let’s make it so that the product menu in the dashboard is empty unless an order is selected. 

Choose the Products data controller in the Project Designer and set its Handler property to ProductsBusinessRules. Browse the app to generate the placeholder file ~/app/App_Code/custom/Rules/Products/ProductBusinessRules.cs. Right-click the controller and choose Edit Handler in Visual Studio.

Enter the following code:
 

 
Method EnumerateDynamicAccessControlRules will impose the access control restrictions when the app is retrieving the data for grid1 view of the Products tagged as myapp-product-menu. This is exactly how the product menu is configured in the dashboard. The name Orders specified in the Filter Source property of the data view field Products is ensuring that the order ID selected in the dashboard is available under the “Orders” alias to the business rules.

If the order ID is not available, then our list of products will be limited to those with the primary key set to -1. Such products do not exist and therefore the user will see the empty list of products.

Otherwise we will deny access to the products that are already linked to the details of the selected order. Such products will not be visible in the product menu.

Trying It Out

Run the app and try populating order details with Cut/Copy/Paste and Drag & Drop. You will notice that the product menu gets shorter as more details are created in the selected order. The framework automatically syncs the details and the product menu with the server after each successful CutPaste, CopyPaste, or DragDrop command.

If you insert a new detail with the help of the New command or delete a few details from the order then the product menu will become out of sync. The selected order is not changed if you perform these operations. The menu will have to be refreshed manually. 

Copy and Cut commands move data to the app clipboard. The data remains there even when you refresh the page or restart the browser and sign in with the user identity. You may want to clear the clipboard after each Paste. 

Paste and Drop do not display a confirmation message and execute instantly. There may be circumstances when the user assent is required.

JavaScript Business Rules

Let’s perfect the syncing of the product menu and provide some pre and post processing when products are pasted or dropped onto the order details.

Create the file ~/app/js/dragdrop.js with the following code. It declares the syncProductMenu() function and the custom client-side business rules for OrderDetails.


The function syncProductMenu()  will locate the product menu on the dashboard and request it to sync once. The default ID of the Dashboard1 data controller instance is view1. The name of the dataview field Products is specified as the argument of syncOnce method. This method will wait for the user interface to stop being busy and sync the data. Subsequent calls to syncOnce will cancel the previous requests to avoid redundant calls. Use this method whenever a dataview on the page requires a data refresh.

The business rule responding to the CopyPaste command will interrupt the execution and display a confirmation. The method $app.confirm returns a promise to the framework. Touch UI will proceed to execute the command if the promise is resolved, which happens when the user agrees to proceed by pressing the OK button in the confirmation prompt. 

The post-processing will sync the product menu after the details are inserted or deleted.

If the copy CopyPaste command has completed successfully, then a custom confirmation with the text describing the clipboard contents is displayed.

The command CutPaste is followed by the clearing of the clipboard.

Advanced Techniques

The default scope of the app clipboard is “global”. Data placed in the clipboard is available on all pages of the app to Paste. You can limit the scope of the clipboard to the current page by setting the option clipboard.scope to “local” in ~/app/touch-settings.json file.

Tags item-paste-Controller and item-drop-Controller make it possible for the user to target individual items in the data view. End users can also paste and drop data by targeting the entire view. There will be situations where the items shall not become the target. Tag view-paste-Controller will make it possible to paste only through the context menu of the dataview. Tag view-drop-Controller will cause the drop target to extend to the entire view when its item is target. 

Cut/Copy/Paste and Drag & Drop are relying on the clipboard to accumulate and perform execution of the CutPaste, CopyPaste, and DragDrop commands. There is no default interpretation for these commands. If your app is relying on the Offline Data Processor to allow transaction input of master-detail records, then the server-side execution of these commands makes little sense. The master-detail data is accumulated and staged by the ODP directly in the WebView. Only the saving of the master record will cause the transaction to be executed on the client. If you want to support the data clipboard and drag & drop with ODP then you will need to write a custom interpretation of the commands in JavaScript.

The live app https://demo.codeontime.com allows cutting and pasting products between supplier and category masters. ODP is enabled on the Categories and Products pages, since their Offline property is set to yes.  ODP is enabled in the "offline" pages loaded in the web browser and also in the disconnected mode when the app is hosted in Cloud On Time. following script implements a custom CutPaste and CopyPaste, which will replace the category or the supplier of the pasted product.


Conclusion

The dashboard can be further enhanced to allow dragging and dropping the order details onto the product menu to provide an alternative method to delete the details.

If the order detail is dropped onto another order, then the detail product can be moved between orders.

The dedicated Products page can provide the Copy and Cut commands. The pasting of the products into Order Details will automatically work on the dashboard page since the clipboard contents are persisted.

If the items in the dataview have a sequential order, then tagging the dataview as item-drag item-drop-Controller will enable the drag & drop movement of items. Use the physical name of the data controller instead of “Controller” in the tag. Implement the business rule to change the item indexes in the response to the DragDrop command.

The consistent user interface of Touch UI makes it possible to create amazing apps with spectacular results that are impossible to achieve with any other tool.

Sunday, June 27, 2021PrintSubscribe
Modal Form Dragging

 Release 8.9.20.0 makes your apps even better!

The responsive forms of Touch UI framework may render in fullscreen mode or as modal popups. Modal forms can now be dragged into arbitrary positions with a touch or mouse pointer. Simply grab the title and move the form to the new position.


Keep dragging the form by the title to reveal more of what is hidden beneath. The forms can be dragged almost entirely offscreen. 



Tap on the background to instantly return to the original position. Setting focus on any field in the form will also restore the position. The resizing of the WebView will have the same effect.



Touch UI has a built-in Drag Manager that works with the scrollbars, column dividers, panels, etc. The most recent use case for the drag manager was the Drawing Pad. Now we have found a new application for this powerful mechanism - modal forms. The following bug fixes are also included in the release:
 
  • (Touch UI) Modal forms support dragging of the form title.
  • (Touch UI) Fixed the issue with the missing function that was not migrated from the touch.js to daf-search.js.
  • (Touch UI) Fixed broken background and column width caused by the scrolling of the grid with the data fields that have "column-width-" tag applied to them. Use the tag to control the precise width of columns in the grids.
  • (Touch UI) Promo button has a pronounced background color change on hover with the mouse pointer.
  • (Touch UI) Fixed the broken Lacquer accent rendered in Dark theme.

Friday, June 25, 2021PrintSubscribe
Drawing Pad, Responsive Grids, Faster Framework

Code On Time release 8.9.19.0 introduces the Drawing Pad and Responsive Grid features along with the significantly improved performance of apps based on Touch UI. 

Performance Enhancements

Touch UI is a very compact framework. As of today the total script library payload stands at 405 kB compressed while the only CSS resource is $49.7 kB compressed. The upcoming new feature Content Hub Add-on will transform the framework into the first rate publishing platform. We are remaking our website, this blog, the help desk, and the new community forum as the Code On Time apps. This imposes various Core Web Vitals requirements and many new features in this release are related to this effort. The framework now performs the pre-loading of web fonts and externalizes the search and import features. As a result all applications re-generated with this release are faster and smaller.

Images in the list items, cards, and forms are not retrieved unless visible. This feature reduces the number of the requests handled by your applications and also benefits the Content Hub pages with the images.

Radio Button List lookup instantly triggers the event to inform the app about the value change and then starts playing the button status change animation. Previously the change event would not trigger until the animation has completed. If your forms have the conditional dependencies on the radio button lists, then the new release will make your app appear more responsive.

Forms with the categories of data fields configured as Wizard steps will appear more responsive if the “steps” include the child DataView fields. The new framework will cause the child data views to fetch values as soon as the “step” contents become visible.

Kiosk UI and UI Automation are significantly faster. The next update will bring about the Camera-based scanner directly in the application.

Drawing Pad

If the image is uploaded as the BLOB field, then the Drawing Pad becomes available.


Default blob field values can now be provided as icons or external image URLs. The former provides a simple way to create the image placeholders as large colorful material icons.The latter introduces the foundation for sketching in your application. 

The upcoming Content Hub will allow drawing on the user-submitted images and screenshots taken directly from the live application when submitting the help desk tickets or creating the community forum posts.

Responsive Grid

The new tag column-width-(tn|xxs|xs|sm|md|lg|xxl)-NNN makes it possible to specify the default and responsive width for individual columns expressed in pixels.


Advanced Search

We are hoping that the subtle change to the Advanced Search will increase its usability. The data fields with the “required” and “suggested” search mode are always included in each “Match” group of fields even if some of the suggestions were not used in the previous search. The end user can progressively engage the suggested fields to refine their search.



The following features, bug fixes, and performance improvements are included:

  • (Touch UI) Enhanced font preloading and eliminating the transparent/missing icons at 90%, 110% and other irregular zoom values in the Chrome, Edge, and Safari.
  • (Touch UI) Clicking anywhere outside of the inline editor will cause auto-post of the row unless initiated with the Escape key or the explicitly selected Cancel command.
  • (Touch UI) New tag modal-title-minimal will force the modal form to display a minimal modal title permanently. Typically the minimal title is displayed in the minimal state only if the modal form content is scrolled down.
  • (Touch UI) Advanced Search will always display the default suggested and required fields in every match group. Previously the suggestions were not visible and only the previous search conditions were retained. The new behavior makes it easier for the end user to refine their search if the previous search has not yielded the desired result.
  • (Universal Input) Enhanced the speed of response of the radio button list. The "click" processing happens before the animation has been completed for a more responsive GUI.
  • (Universal Input) Lookup data field tagged as lookup-auto-advance will migrate to the next input in the form.
  • (Universal Input) Lookup data field tagged as lookup-auto-advance-row will migrate to the next input in the same row container.
  • (Universal Input) Radio button list uses the styling that does not create an empty dot in the middle of the selected radio button list on some monitors. If lookup-auto-advance tag is applied then the "focus" frame is not displayed during the transition from the radio button list to the next input.
  • (Blob) Drawing Pad is available to markup the images directly in the app.
  • (Touch UI) Option ui.menu.position controls the position of the navigation menu in the sidebar.  The default is top. The second supported value is bottom.  Requires ui.menu.location to be set to sidebar in touch-settings.json. Previously the sidebar menu always displayed at the bottom of the sidebar by default.
  • (Model Builder) Enhanced serialization of the database metadata uses a simple loop instead of the recursive calls and improves ability to handle huge databases faster. Previously a database with more that 1500 tables has failed to serialize due to the stack overflow.
  • (Touch UI) The default dedicated login page created by the app generator is now programmed to allow the app to decide the landing page after the successful login. The URL returned by the method ApplicationServices.UserHomePageUrl() will determine the landing page. The default landing page is ~/pages/home. Override the method the partial class implementation to introduce your own landing pages.
  • (Touch UI) Wizard form buttons are correctly refreshed when the form is opened in the reading pane.
  • (Framework) Logout will not cause the exception in the server-side code when vi-VN culture is set.
  • (Touch UI) New tag column-width-(tn|xxs|xs|sm|md|lg|xl)-NNN will define the precise width of the grid column for a particular page width.
  • (Touch UI) Modal form with fitted height ignores the virtual keyboard stub when calculating the height.
  • (Touch UI) Font preloading instruction is included in the pages automatically.
  • (Touch UI) Externalized import API into ~/js/daf/daf-search.js to reduce the required footprint of Touch UI.
  • (Touch UI) Externalized implementation of import into ~/js/daf/daf-import.js to reduce the size of the core framework.
  • (Framework) Method $app.saveFile(name, text, type) will cause the WebView to display a prompt to save a file with the given name text in UTF-8 encoding with the option type, which defaults to text/plain.
  • (Import) Import handles the child data view lookup fields that have their names not matched with the master table field name.
  • (Touch UI) Collapsible menu in the sidebar will not be visible when expanding/collapsing transition is intersecting with the sidebar mini calendar.
  • (Touch UI) Blob thumbnail will open a "save file" prompt when clicked. Previously the internal preview popup was displayed.
  • (Touch UI) Blob thumbnail will open a "save file" prompt when clicked. Previously the internal preview popup was displayed.
  • (Blob) If the  blob field is tagged as image-user-defined-none then tap on the image will activate the drawing pad. Otherwise the file selection window is presented.
  • (Touch UI) Numerous core classes from the legacy jQuery Mobile have been removed for improved performance.
  • (Touch UI) Item in the panels do not trigger taphold.
  • (Multifile Upload) Drawing pad is available if only one file is selected for upload.
  • (Multifile Upload) The names of the files are automatically trimmed if they exceed the length of the "name" field. Previously the upload was rejected due to inability to insert the placeholder record into the database.
  • (Framework) The external filter of the parent is passed when actions are executed on the child data view when there is not direct master-detail relationship between the two.
  • (Framework) The external filter of the child data view is included with the Execute requests in its forms.
  • (Framework) Multi-file upload will pass the external filter of the data view with the Insert requests.
  • (Blob) Field tagged as image-editor-none will not allow manipulation of the image on the client.
  • (Blob) Clearing of the blob in the form will trigger getdefaultblob.app event on the document to allow the default value to be supplied.
  • (Blob) Event getdefaultblob.app will cause the drawing of default image as a material icon if e.blob.icon property is specified. The optional color can be specified in e.blob.color property.  The default image based on the icon is drawn only if the blob field is tagged as image-size-WxH where W and H are the width and the height of the default image.
  • (Framework) New method $app.intersect returns true if the two objects specified in the augments are intersecting. Objects may represent the ( x,y) point, the rectangle, or the DOM element.
  • (Universal Input) New "slider" input is now a part of the framework.
  • (Touch UI) The alert popup displays the message as a note to ensure that the entire text is visible.
  • (Framework) Html detection also includes the search for encoded characters and symbols.
  • (Survey) Enhanced error reporting when loading survey definition from the server.
  • (Kiosk UI) Modal background and glass pane are invisible if the Kiosk UI is displayed above the app.
  • (Touch UI) Fullscreen pages without gap with the buttons will take into account the safe area at the bottom on iOS devices.
  • (Barcodes) Significantly improved performance of the barcode processing during UI Automation. Automation processor uses a fast check for the first IfThisThenThat condition to trigger in response to the barcodes triggered. App pages of the app are ansible while the Kiosk UI is active.
  • (Touch UI) Eliminated the double divider at the bottom of the list of items in the sidebar.
  • (Touch UI) Tooltips of the buttons in the fullscreen form without gaps are displayed above the parent toolbar.
  • (Blob) Image preview is not draggable in the desktop browsers.
  • (Touch UI) Image loading observer will keep track of resolved/observed URLs for enhanced performance.
  • (Touch UI) Method $app.touch.observe(url) will return the observed URL if the URL has been observed already on the page.
  • (Touch UI) Method $app.touch.observe(enable, container) will start observing the element visibility.
  • (Upload) Dropping the non-file content on the drop target will not cause the field to clear.
  • (Touch UI) Field footer text of  empty values is NOT displayed in "lower-case". 
  • (Touch UI) Method $app.touch.show({headerText: 'Text 1', controller: 'c1', startCommand: 'New', startArgument:'createForm1'}) will correctly assign the  value of the headerText option to the page header of the form when the command option is set to New.
  • (Touch UI) Method $app.touch.pointrer('pen') returns true if the last touch was with the "pen" pointer.
  • (Virtual Keyboard) Virtual keyboard is not activated if the input is touched with the "pen" pointer. It allows the user to write on top of the input without interruption.
  • (Universal Input) The numeric input type is not set to "number" on mobile devices if the input was touched with the "pen" pointer.
  • (Touch UI) Click the blob drop area will cause the BLOB field to become focused.
  • (Blob) Drawing survey is displayed when "draw" icon is tapped.
  • (Touch U) If the "fullscreen" button is hidden with the modal-buttons-fullscreen-none then the button on the left side of it is shifted to the right to fill the gap.
  • (Display Flow Designer) Arrow keys Up/Left/Down/Right with Shift and Control modifiers will select / deselect display objects in the flow if the there is no active text input.
  • (Data Aquarium) Command Search will activate the confirmation controller specified as _controller=Name variable in the Confirmation property of the action. It will restore the previous search values. The search is cleared when the filter is  canceled by the user.
  • (Touch UI) Custom search is activated when the controller with Search action in Action Bar scope is specified as the lookup of another controller.
  • (Data Aquarium) Action with command name Search will not cause the  SyncKey data conversion error on the server.
  • (Display Flow) Ctrl|Shift + Up|Left|Down|Right will make the first/last selected display object visible in the WebView.
  • (Touch UI) Default values for BLOB fields are now supported.  The getdefaultblob.app event handler will specify the default blob file for the field. The specified file is automatically downloaded and selected as the blob value.
  • (Framework) $app.getScript loads the dynamic dependencies and executes the callback when the resources and their dependencies are available.
  • (Display Flow) "Code" blocks render with the Code Mirror in IE11.
  • (Display Flow Designer) All  resources of Code Mirror are loaded on demand when the "code" display objects are included in the display flow.
  • (Display Flow) "Code" display blocks are provided with a caption showing the code type and the optional description.
  • (Data Aquarium) Files codemirror.min.js and codemirror.min.css are included in ~/js/lib folder when the app is generated. This library is automatically loaded in Display Flow pages with the code blocks (sample C#, HTML, JavaScript, etc.)
  • (Touch UI) Multiple keyboard shortcuts for the same char code are now supported. For example, Ctrl+V and Ctrl+Shift+V will paste the content in Display Flow page before and after the selected block of display objects.
  • (Display Flow Designer) Copy and Cut work with the internal buffer to allow easy manipulation of the content.
  • (Touch UI) Typography of H1-H6 tags in two different variations and the jumbo version. The second large font size starts on "large" screens (>= 992px)
  • (Touch UI) Method $app.elementAt(p) returns the jQuery element at the specified point in the page. If there is no argument, then the element at the last touch/click point is returned.
  • (Touch UI) Optimized the code base to use $app.clientRect and $app.elementAt methods.
  • (Touch UI) Reduced the right margin of material icons to 1/20 of the element in Bootstrap and Display Flow content pages. 
  • (Bootstrap) Removed the leading spaces after the material icons in the Bootstrap content templates.
  • (Touch UI) Material icons have the fixed width of 1em in the Bootstap and Display Flow pages to avoid the horizontal shifting while the stylesheets are loading.
  • (Data Aquarium) Method $app.getScript(url, callback) will load the script from the app and invoke the callback. It enables dynamic loading of client library files with support for debugging in Visual Studio.
  • (Touch UI) New dynamic BLOB image loading will delay the loading of image thumbnails until the image is in the view of the end user.
  • (Framework)  Meta tag  <meta http-equiv="X-UA-COMPATIBLE" content="IE=Edge" /> is added to the page on the server if IE 11 client is detected.
  • (Framework) Content Type header of combined CSS and JavaScript is provided with the chartset=utf-8 instruction.
  • (Framework) Meta definition of the character set is the first element of the page head element.
  • (Framework) Meta tags of the page are not closed.
Labels: Release Notes