Skip to content

Interactive Resource Editing

Rick Strahl edited this page Apr 16, 2015 · 23 revisions

Westwind.Globalization supports resource editing on source HTML pages by providing optional links in these pages to link directly to the referenced resources in the Web based resource editor. Essentially resource icons are added to all HTML elements that include a data-resource-id element, which in turn highlights the specified element with a clickable icon, that when clicked opens the localization admin form with the specified resource highlighted:

Resource Edit View adds clickable icons

This is the Web Resource Editor with Resource Editing Links enabled (how meta of me, huh?). When you click any of the red flags, a new window opens with another copy of the Resource Editor (and no edit flags) pre-set on the selected resource if one is matched. In effect if you have the right markup in the page any HTML page can be made to link to the resource editor.

Usage

In order for elements in your Web Page to be linked for resource editing you need to mark them up with two supported attributes:

  • data-resource-id
    The specific resource id of the element to link to. This attribute needs to be attached to any element that is associated with the resource.

  • data-resource-set
    The resource set that that the resource belongs to. This can be declared on the actual element or anywhere in the parent element hierarchy. The library searches up the tree to find the nearest data-resource-set attribute and uses its value.

In practice you typically declare the resource set at the <body> or some wrapper 'view-level' element and resource ids for each element to display. Here's what this might look like:

<body data-resource-set="LocalizationForm">
   <div class="page-title" 
        data-resource-id="PageTitle">
     @DbRes.T("PageTitle")
   </div>

   <-- if you have non-wrapped text you can add a <span> tag -->
   <span data-resource-id="HelloWorld">@Resources.HelloWorld</span>
</body> 

For WebForms there's a special DbResourceControl that automatically generates the resource link for most Web Controls so you don't have to explicitly set the attributes.

Enabling Resource Links

In order to get the resource icons to load you need to load ww.resourceEditor.js library. The library has a dependency on jQuery so you first need to load jQuery if your application doesn't already load it. You can use a CDN link or your local copy, or use the copy provided by the LocalizationAdmin application:

<script src="LocalizationAdmin/bower_components/jquery/dist/jquery.min.js"></script>

Next add the actual ww.resourceEditor.js script:

<script src="localizationAdmin/scripts/ww.resourceEditor.js"></script>

When you're ready to actually display the editing icons make a call to showResourceIcons():

ww.resourceEditor.showResourceIcons({ adminUrl: "./LocalizationAdmin/" });

You have to provide an adminUrl which points at the resource editor and defaults to ./LocalizationAdmin/. This URL is used to generate the target links when you click on the resource links. The URL is appended with query string values for ResourceSet,ResourceId and Content which are used to look up or add new resources to the Web Resource Editor.

When you want to hide the icons you can use:

ww.resourceEditor.removeResourceIcons();

Typically you use these two methods from buttons somewhere in your UI, that enable or disable resource editing, so this code is fired typically from a button click or other user action of some sort.

CSS and FontAwesome

You'll also need some CSS that determines editable icons display. By default FontAwesome is used for the flag icon, but you can change that by modifying the .resource-editor-icon:before style and removing the FontAwesome font reference and changing the character displayed to a standard character (like a # for example):

<!-- optional - if you don't use change the CSS to display plain character -->
<link href="./LocalizationAdmin/bower_components/fontawesome/css/font-awesome.min.css"
      rel="stylesheet"/>

<style>            
.resource-editor-icon, .resource-editor-icon:hover,  .resource-editor-icon:visited {
    position: absolute;
    display: inline;
    height: 13px;
    width: 13px;     
    text-decoration: none;
    zIndex: 999999;                 
    margin: -14px 0 0 -2px;
    cursor: pointer; 
    opacity: 0.45;                                   
}
.resource-editor-icon:hover {
    opacity: 1;         
}
.resource-editor-icon:before {
    font-family: fontawesome;
    content: "\f024";   /*flag*/ 
    /*font-family: Arial;
    content: "#";*/
    font-size: 9pt;              
    color: red;                      
}
</style>

You can add the style to individual pages or to a global style sheet.

How it works

This resource editing mechanism is based on a client side JavaScript implementation that checks for specific attributes on DOM elements and then injects icon overlays into the HTML document to provide clickable links that open the Resource Editor with the selected resources active.

Attribute based Resource Identification

The icons are attached to HTML elements that have a specific data-resource-id attribute. In addition a data-resource-set attribute has to exist to identify the resource set, either on the same HTML element or at an element along the parent DOM tree.

On typical pages you'll have a set up like this:

<body data-resource-set="LocalizationForm">
   <div class="page-title" 
        data-resource-id="PageTitle">
     @DbRes.T("PageTitle")
   </div>

   <-- if you have non-wrapped text you can add a <span> tag -->
   <span data-resource-id="HelloWorld">@Resources.HelloWorld</span>
</body> 
Any HTML Page can be Marked Up

The data-resource-id attribute can be attached to any element on an HTML page. In the example above the first element is already wrapped into a <div> tag and so I can simply attach the attribute to the parent. In the second example the text originally was just plain free standing text without any wrapping element - I added a <span> tag around the element to allow attaching of the data-resource-id attribute.

Since the logic is based on pure HTML and JavaScript, this mechanism works with any server side as well as any client side technology. Above I'm using DbRes.T() and strongly typed resources as an example here to embed the actual values.

WebForms

In ASP.NET WebForms pages that use meta:resourcekey tags you can use a DbResourceControl that can automatically generate the data-resource-id and data-resource-set attributes for any WebControls on the page so you don't have to manually create the attributes.

Pure Client Side and AngularJs

For client side code the usage is still the same. For example the following uses AngularJs binding expressions and the usage of the attributes is identical:

<li>
    <a ng-show="view.resourceSets && view.resourceSets.length > 0"
        data-toggle="modal" data-target="#CreateClassDialog"
        title="{{view.resources.CreateClass_Title}}"
        data-resource-id="CreateClass">
        <i class="fa fa-code" style="font-weight: bold;"></i> {{::view.dbRes('CreateClass')}}
    </a>
</li>
<li>
    <a ng-show="view.resourceSets && view.resourceSets.length > 0"
        ng-click="view.onReloadResourcesClick()"
        title="{{view.dbRes('ReloadResources_Title')}}"
        data-resource-id="ReloadResources">
        <i class="fa fa-refresh"></i> {{::view.dbRes('ReloadResources')}}
    </a>
</li>

Again notice the data-resource-id attributes in both of the elements.

What gets generated

Behind the scenes this library runs through the document and essentially injects DOM elements into the page that represent the icons. The icons are overlaid ontop of the existing DOM element as a small semi-transparent icon that is clickable.

The actual rendered runtime HTML for one of the icons and it's host element looks like this:

<!-- injected element -->
<res-edit class="resource-editor-icon" 
          target="resourceEditor" 
          title="Edit resource" 
          onclick="window.open('./?ResourceSet=LocalizationForm&amp;ResourceId=Add','resourceEdit')" 
          style="top: 0px; left: 0px;"></res-edit>

 <!-- original element -->
 <button class="btn btn-sm btn-default ng-binding" 
         title="Add new ResourceSet" 
         ng-click="view.onAddResourceClick()" 
         data-resource-id="Add">
    <i class="fa fa-plus"></i> Add
</button>

Why a <res-edit> tag? I used a custom tag name to avoid any CSS bleed issues with links or div tags. I had originally used an anchor tag, but I ran into formatting problems as CSS formatting for links would affect the rendering. Using a custom tag minimizes - but doesn't entirely remove - these problems.

Enabling/Disabling Edit Mode

In typical applications you'll want to provide resource edit links only in special admin modes and even then only when you explicitly decide to edit resources. Otherwise the icons just get in the way, as well as causing overhead in their generation into the page.

For this reason the icons are not visible by default and you have to explicitly call the ShowResourceIcons() function.

For example, in the LocalizationAdmin edit form I enable and disable resource editing with two menu options which are alternately displayed or hidden depending on the state of a view variable in the AngularJs model.

Here's what the click code that is called from either of those buttons looks like to enable and disabling resource editing:

vm.showResourceIcons = function () {
    vm.resourceEditMode = !vm.resourceEditMode;
    if (vm.resourceEditMode)
        ww.resourceEditor.showResourceIcons({ adminUrl: "./" });
    else
        ww.resourceEditor.removeResourceIcons();
};

You can check out this behavior in the actual Localization Admin form which is localizable and then links to itself in edit mode.

Summary

Resource editing with linkable resources is very useful in dynamic applications that allow editing of content for localization (as well as basic content editing). Although it requires a little bit of setup, plus adding extra attributes onto content, this feature provides an easy way to make applications dynamically editable for localization. The DbResourceControl for WebForms provides an even easier approach as most WebControls can automatically be linked for resource editing.

Related Resources

Please also see:

Clone this wiki locally