Quick Snippet: Toggle Tree Navigation in Umbraco Backoffice using JavaScript

Hello,
Here is a very quick blog post on how to toggle the tree navigation in the Umbraco 7 (aka Belle) back office using JavaScript with some AngularJS services that the Umbraco core team has given to us to use.

First of all you may be wondering why you would want to toggle the display of the tree navigation, considering that this is the main & primary navigation when using the Umbraco backoffice, however on a project I am doing at work a new property editor that is being developed requires more screen real estate and toggling the tree navigation allows the content editor to see & use this property editor a lot easier, as it involves plotting objects on a canvas. So as much space as possible is useful in this case.

So enough of the why and I will get straight down to the very simple JavaScript code snippet that allows us to do this:

angular.module('umbraco').controller('demo.toggler', function($scope, appState, eventsService) {
  //Create an Angular JS controller and inject Umbraco services appState & eventsService

  //Button Click - ToggleUmbracoNavigation
  $scope.toggleUmbracoNavigation = function() {

    //Get the current state of showNavigation
    var currentNavigationState = appState.getGlobalState('showNavigation');

    //console.log("currentNavigationState", currentNavigationState);
    //console.log("Inverse of currentNavigationState", !currentNavigationState);

    //Toggle the tree visibility
    appState.setGlobalState("showNavigation", !currentNavigationState);
  }

  //The eventService allows us to easily listen for any events that the Umbraco applciation fires
  //Let's listen for globalState changes...
  eventsService.on("appState.globalState.changed", function (e, args) {
    //console.log("appState.globalState.changed (args)", args);

    if (args.key === "showNavigation") {
      //console.log("showNavigation value", args.key, args.value);

      //If false (So hiding navigation)
      if(!args.value) {
        //Set css left position to 80px (width of appBar)
        document.getElementById("contentwrapper").style.left = "80px";
      }
      else {
        //Remove the CSS we set so default CSS of Umbraco kicks in
        document.getElementById("contentwrapper").style.left = "";
      }
    }
  });

});

Hopefully the JavaScript is commented enough and is easy to follow, but the ensence of this is that we have a button or anchor link in our view with the Angular directive of ng-click applied to it calling out method, i.e ng-click=”toggleUmbracoNavigation()” this toggles the value stored in Umbraco’s globabl settings in this case these values & settings are stored in an AngularJS service called appState, that allows us to get & set values stored in here. I recommend you look at the source code on GitHub to see what other values are stored in appState for you to use in your customisations to the Umbraco back office.

I would be interested to hear what other people think of this and should this tree toggle become part of the core by doing a Pull Request and if was to become part of the main UI, where should the button go or by double clicking the grey area with the application/section icons toggle this action?

Well let me know by leaving your thoughts in the comments.

Thanks,
Warren 🙂

Restrict Umbraco Media Filesize with JS

Hello all,
This is a very quick & brief blog post for a quick code snippet. I had a requirement today to at The CogWorks restrict file size upload for media items in Umbraco and to display a friendly error message.

For this to work easily, I created a .NET usercontrol with the following in:


<script type="text/javascript">
 //Go get file size from .config value in bytes
 var fileSizeToCheck = <%= ((HttpRuntimeSection) ConfigurationManager.GetSection("system.web/httpRuntime")).MaxRequestLength %>
</script>
<script type="text/javascript" src="/usercontrols/MediaFileSize/MediaFileSizeValidation.js"></script>

<div id="fileSize"></div>

The next part was to create a custom document type in Umbraco using the UserControl Wrapper method and pointing the datatype to my newly created usercontrol.

The next step was to assign this document type as a property on my image media type. I gave it name like FileSize Check, however this name does not matter as I do not use the property value at all, it’s only purpose is to run the custom Javascript inside it, which is as follows:

//When DOM ready
$(function () {
    
    //Get the File Size DOM element & hide it's label & property area
    $('#fileSize').closest('.propertypane').hide();

    //On form submit
    $("form").on("submit", function (event) {

        //Get the file input type
        var fileInput = $("input[type=file]")[0];

        console.log(fileInput);
        console.log(fileSizeToCheck);

        //Validate filesize
        if (!validateFileSize(fileInput, fileSizeToCheck)) {
            
            //Show validtion message
            UmbClientMgr.mainWindow().UmbSpeechBubble.ShowMessage('error', 'File Size', 'The file chosen is too big, please choose a smaller file than ' + fileSizeToCheck/1024 + 'kb');
            
            //Cancel form event
            event.preventDefault();
        }        
    });
});

///http://deepeshdarshan.wordpress.com/2012/06/20/how-to-validate-upload-file-size-and-file-extension-using-javascript/
function validateFileSize(component, maxSize) {
    
    if (navigator.appName == "Microsoft Internet Explorer") {
        if (component.value) {
            var oas = new ActiveXObject("Scripting.FileSystemObject");
            var e = oas.getFile(component.value);
            var size = e.size;
        }
    }
    else {
        if (component.files[0] != undefined) {
            size = component.files[0].size;
        }
    }
    
    if (size != undefined && size > maxSize) {
        component.value = "";
        component.focus();
        
        return false;
    }
    else {
        return true;
    }
}

As you can see from the JavaScript I first hide the property from the Umbraco backoffice UI, as we don’t need to show a label and an emtpy box for the media UI, but the main part of the code hooks into the form on submit event and then grabs the file input type and passes it to the validateFileSize function(). If the file is too big then we display an error message using the Umbraco message notification bubble in the bottom right hand corner.

Well that’s all there is to it.
Hopefully this little snippet will have helped you out.

Cheers,
Warren 🙂

Highlight Errors in CodeMirror

Hello all,
With the release of Optimus for Umbraco that me & Tim Geyssens have built that allows you to create bundles and write Sass, Less, CoffeeScript & TypeScript files directly inside Umbraco.

We wanted a way to highlight any compiling errors with your code that you write, by highlighting the line number in the editor of the Umbraco back office.

The code editor inside Umbraco, uses the highly popular HTML & JavaScript code editor CodeMirror. My goal was to highlight the exact line number in the editor so we can visually highlight to the user where in their code that is the problem.

So I will take you through the small code snippet that was used to achieve this:

In the FileEditor.aspx page that we have I wrote the following JavaScript function

    function highlightLine(lineNumber) {

        //Line number is zero based index
        var actualLineNumber = lineNumber - 1;

        //Select editor loaded in the DOM
        var myEditor = $("#body_EditorSource .CodeMirror");

        //Write the item to the console window, for debugging
        console.log(myEditor);

        //Select the first item (zero index) just incase more than one found & get the CodeMirror JS object
        var codeMirrorEditor = myEditor[0].CodeMirror;

        //Write the item to the console window, for debugging
        console.log(myEditor[0].CodeMirror);

        //Set line CSS class to the line number & affecting the background of the line with the css class of line-error
        codeMirrorEditor.setLineClass(actualLineNumber, 'background', 'line-error');
    }

In addition to this I need a small chunk of CSS in order to style the error line in red for it to be easily noticed.

<style>
        .line-error {
            background: #FBC2C4 !important;
            color: #8a1f11 !important;
        }

</style>

The final thing that needs for this all to come together and work, is that when the save button is hit on our custom code editor page, that we check for any errors from the transformers such as Sass & CoffeeScript for example. Parse the line number and pass that to our Javascript function highlightLine().

        private bool SaveConfigFile(string filename, string contents)
        {
           //This gets the filename of the Sass, Less, CoffeeScript or TypeScript file
            var path = Request.QueryString["path"] + filename;

            //This gets the full path to the file (Server MapPath'd)
            var fullPath = Server.MapPath(Request.QueryString["path"]) + filename;

            //Open up the file on disk
            using (var text = File.CreateText(fullPath))
            {
                //Save the file contents
                text.Write(contents);

                //Close the text reader, as we are done with it
                text.Close();

                //Check the translation for errors
                var errors = transCore.ValidateTranslation(path);

                //If no errors then...
                if (errors == null || !errors.Any())
                {
                    //Save the translation to disk
                    transCore.SaveTranslation(path);
                    return true;
                }
                else
                {
                    //Get the first exception message out of the collection
                    var exceptionMessage = errors.First().Message;

                    //Set the panel on the page - it's an error type & show the exception message
                    Feedback.type = Feedback.feedbacktype.error;
                    Feedback.Text = exceptionMessage;
                    Feedback.Visible = true;

                    //Get Line number from the exception message - presumes messages always ends with
                    //Line number: 3
                    var lineNumber = exceptionMessage.Split(' ').Last().Replace("\r", "").Replace("\n", "");
                    int.TryParse(lineNumber, out ErrorLineNumber);

                    return false;
                }
            }

So that’s all the parts of our code that enables us to highlight the line number in the CodeMirror editor.

There is plenty more that could be done with the editor, as there are many options available to us when we have the CodeMirror object selected in JavaScript. So let your imagination go wild and start playing around with the code editor inside Umbraco.

Any questions please leave them in the comments.

Thanks,
Warren 🙂