Преглед изворни кода

add context menu management

Anonymous пре 10 година
родитељ
комит
3975981fce
10 измењених фајлова са 307 додато и 252 уклоњено
  1. 8 8
      app/main.js
  2. 27 8
      app/shell.html
  3. 22 22
      app/shell.js
  4. 32 22
      app/widgets/filebrowser/view.html
  5. 61 55
      app/widgets/filebrowser/viewmodel.js
  6. 5 5
      bower.json
  7. 125 118
      data/filesystem.json
  8. 11 5
      index.html
  9. 7 9
      style/filebrowser.less
  10. 9 0
      style/global.less

+ 8 - 8
app/main.js

@@ -1,15 +1,15 @@
 requirejs.config({
 	paths: {
-		'text'					: '../lib/requirejs-text/text',
-		'durandal'				: '../lib/durandal/js',
-		'plugins'				: '../lib/durandal/js/plugins',
-		'transitions'			: '../lib/durandal/js/transitions',
-		'knockout'				: '../lib/knockout.js/knockout',
+		'text'						: '../lib/requirejs-text/text',
+		'durandal'					: '../lib/durandal/js',
+		'plugins'					: '../lib/durandal/js/plugins',
+		'transitions'				: '../lib/durandal/js/transitions',
+		'knockout'					: '../lib/knockout.js/knockout',
 		'knockout.mapping'		: '../lib/bower-knockout-mapping/dist/knockout.mapping.min',
 		'knockout.validation'	: '../lib/knockout-validation/dist/knockout.validation.min',
-		'jquery'				: '../lib/jquery/jquery.min',
-		'perfect.scrollbar'		: '../lib/perfect-scrollbar/js/perfect-scrollbar.jquery',
-		'highlightjs'			: '../lib/highlightjs/highlight.pack'
+		'jquery'						: '../lib/jquery/jquery.min',
+		'perfect.scrollbar'		: '../lib/perfect-scrollbar/js/perfect-scrollbar.jquery',
+		'highlightjs'				: '../lib/highlightjs/highlight.pack'
 	},
 	shim: {
 		'knockout.mapping': {

+ 27 - 8
app/shell.html

@@ -1,15 +1,34 @@
 <div class="row-fluid">
-	<aside class="col-md-3" id="filebrowser">
+	<aside class="col-sm-2 col-md-2">
 		<div data-bind="widget: {kind:'filebrowser'}"></div>
 	</aside>
-	
-	<main class="col-md-6" id="main">
+	
+	<main class="col-sm-10 col-md-6" id="main">
 		<pre data-bind="visible: content">
-			<code data-bind="attr: {css: type}, text: content" id="editor"></code>
-		</pre>
+			<code data-bind="attr: {css: type}, text: content" id="editor"></code>
+		</pre>
 		<span class="text-center" data-bind="visible: !content()">Open file to view it.</span>
 	</main> 
-	
-	<aside class="col-md-3" id="helpPane">
-	</aside>
+	
+	<aside class="col-sd-12 col-md-4" id="helpPane">
+		<h2>Welcome to the filebrowser Durandal widget demo</h2>
+		<p>
+			This <a href="" target="_blank">Durandal</a> widget allows to display a folder tree and add some actions to manipulate this items.
+			<ul>
+				<li>A clic on a file or folder selects it. Multiple select is possible holding the <kbd>Ctrl</kbd> key</li>
+				<li>A double-clic opens / closes a folder</li>
+				<li>A double-clic displays the file content in the editor</li>
+				<li>
+					A right-clic opens a context menu with different options :
+					<ul>
+						<li>Rename the item</li>
+						<li>Copy the selected item(s)</li>
+						<li>Paste the selected item(s)</li>
+						<li>Create an item (in a folder)</li>
+						<li>Delete an item (and its components)</li>
+					</ul>
+				</li>
+			</ul>
+		</p>
+	</aside>
 </div>

+ 22 - 22
app/shell.js

@@ -1,26 +1,26 @@
-define(['durandal/app', 'knockout', 'highlightjs'], function (app, ko) {
-	var type = ko.observable(),
-		content = ko.observable();
-	
-	var sub = app.on('filebrowser:open_file').then(function(message) {
-		type(message.type);
-		if( message.type === "json" ) {
-			content(ko.utils.stringifyJson(message.content));
-		} else {
-        	content(message.content);
-        }
-        hljs.highlightBlock($('#editor')[0]);
-    }, this);
-
-
-	return {
-		attached: function () {
-			hljs.configure({
-			  tabReplace: '  '
-			});
+define(['durandal/app', 'knockout', 'highlightjs'], function (app, ko) {
+	var type = ko.observable(),
+		content = ko.observable();
+	
+	var sub = app.on('filebrowser:open_file').then(function(message) {
+		type(message.type);
+		if( message.type === "json" ) {
+			content(ko.utils.stringifyJson(message.content));
+		} else {
+        	content(message.content);
+        }
+        hljs.highlightBlock($('#editor')[0]);
+    }, this);
+
+
+	return {
+		attached: function () {
+			hljs.configure({
+			  tabReplace: '  '
+			});
 			hljs.initHighlighting();
-		},
-		type: type,
+		},
+		type: type,
 		content: content
 	};
 });

+ 32 - 22
app/widgets/filebrowser/view.html

@@ -1,29 +1,32 @@
-<div id="filebrowser" class="filebrowser">
-	<!-- ko if: folder() -->
-		<!-- ko let: { loopRoot: $data } -->
-			<ul data-bind="template: { name: 'tree-template', foreach: folder().children() }" class="tree-file"></ul>
+<div id="filebrowser">
+  <!-- ko if: folder() -->
+		<!-- ko let: { loopRoot: $data } -->
+			<ul data-bind="template: { name: 'tree-template', foreach: folder().children() }" class="tree-file"></ul>
 		<!-- /ko -->
-	<!-- /ko -->
-	<span data-bind="visible: !folder()" class="text-center">Loading workspace...</span>
+	<!-- /ko -->
 
 	<script id="tree-template" type="text/html">
 		<!-- ko if: $data.type() === "folder" -->
-			<li class="folder">
-				<i class="fa fa-folder-o" data-bind="attr: {id: 'icon_folder_' + $data.uuid()}"></i>
-				<span data-bind="text: $data.name, event: { dblclick: loopRoot.openFolder, contextmenu: loopRoot.openContextMenu, click: loopRoot.select }"/>
+			<li class="folder">
+				<span data-bind="event: { contextmenu: loopRoot.openContextMenu, dblclick: loopRoot.open, click: loopRoot.select }">
+					<i class="fa fa-folder-o" data-bind="attr: {id: 'icon_folder_' + $data.uuid()}"></i>
+					<!-- ko text: $data.name --><!-- /ko --> 
+				</span>
 				<input type="checkbox" data-bind="attr: {id: $data.uuid}" />
 				<ul data-bind="template: { name: 'tree-template', foreach: $data.children }"></ul>
 			</li>
 		<!-- /ko -->
 		<!--ko if: $data.type() !== "folder"-->
-			<li data-bind="attr: {'data-id': $data.uuid, 'data-filetype': $data.type()}" class="file">
+			<li data-bind="attr: {'data-id': $data.uuid, 'data-filetype': $data.type()}, 
+         					event: { contextmenu: loopRoot.openContextMenu, dblclick: loopRoot.open, click: loopRoot.select }" 
+         	 class="file">
 				<!--ko ifnot: $data.type -->
-				<i data-bind="attr: {class: 'fa fa-file-o'}"></i>
+					<i data-bind="attr: {class: 'fa fa-file-o'}"></i>
 				<!-- /ko -->
 				<!--ko if: $data.type -->
-				<i data-bind="attr: {class: 'fa fa-file-' + $data.type() + '-o', title: $data.type()}"></i>
+					<i data-bind="attr: {class: 'fa fa-file-' + $data.type() + '-o', title: $data.type()}"></i>
 				<!-- /ko -->
-				<span data-bind="text: $data.name, event: { dblclick: loopRoot.openFile, contextmenu: loopRoot.openContextMenu, click: loopRoot.select }, attr: {'data-extra': $data.extra ? $data.extra : ''}"></span>
+				<span data-bind="text: $data.name, attr: {'data-extra': $data.extra ? $data.extra : ''}"></span>
 			</li>
 		<!-- /ko -->
 	</script>    
@@ -31,16 +34,23 @@
 	<!-- Context menu -->
 	<div id="fileBrowserContextMenu" class="dropdown open" data-bind="visible: showContextMenu" tabindex="1">
 		<ul class="dropdown-menu" role="menu" aria-labelledby="contextMenu">
-			<!-- ko if: selected() != undefined && !selected().extra -->
-			<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-bind="click: newItem">New ...</a></li>
-			<!-- /ko -->
-			<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-bind="click: openRenamePopup">Rename</a></li>
-			<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-bind="click: copy">Copy</a></li>
-			<!-- ko if: selected() != undefined && !selected().extra -->
-			<li role="presentation" data-bind="css: { 'disabled': !hasCopied()}"><a role="menuitem" tabindex="-1" href="#" data-bind="click: paste">Paste</a></li>
-			<!-- /ko -->
-			<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-bind="click: openDeletePopup">Delete</a></li>
+			<li data-bind="visible: hasSelectedFolder()" >
+				<a role="menuitem" tabindex="-1" href="#" data-bind="click: newItem">New ...</a>
+			</li>
+			<li>
+				<a role="menuitem" tabindex="-1" href="#" data-bind="click: openRenamePopup">Rename</a>
+			</li>
+			<li>
+				<a role="menuitem" tabindex="-1" href="#" data-bind="click: copy">Copy</a>
+			</li>
+			<li data-bind="css: { 'disabled': !hasCopied()}, visible: hasSelectedFolder()">
+				<a role="menuitem" tabindex="-1" href="#" data-bind="click: paste">Paste</a>
+			</li>
+			<li>
+				<a role="menuitem" tabindex="-1" href="#" data-bind="click: openDeletePopup">Delete</a>
+			</li>
 		</ul>
 	</div>
+  
 	<!-- End of Context menu -->
 </div>

+ 61 - 55
app/widgets/filebrowser/viewmodel.js

@@ -4,69 +4,74 @@ define(['durandal/app', 'durandal/composition', 'plugins/http',
         './renameModal', './newItemModal'],
         function(app, composition,http, $, ko, ko_mapping, perfectScrollbar, RenameModal, NewItemModal) {
 
-	ko.mapping = ko_mapping;
-	
-	ko.bindingHandlers['let'] = {
-	    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
-	        // Make a modified binding context, with extra properties, and apply it to descendant elements
-	        var innerContext = bindingContext.extend(valueAccessor());
-	        ko.applyBindingsToDescendants(innerContext, element);
-	
-	        return { controlsDescendantBindings: true };
-	    }
-	};
+	ko.mapping = ko_mapping;
+	
+	ko.bindingHandlers['let'] = {
+	    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+	        // Make a modified binding context, with extra properties, and apply it to descendant elements
+	        var innerContext = bindingContext.extend(valueAccessor());
+	        ko.applyBindingsToDescendants(innerContext, element);
+	
+	        return { controlsDescendantBindings: true };
+	    }
+	};
 	ko.virtualElements.allowedBindings['let'] = true;
     
-    var ctor = function() { },
-        selected = ko.observableArray(),
-        showContextMenu = ko.observable(false),
+    var ctor = function() {},
+        selected = ko.observable(),
+        showContextMenu = ko.observable(),
         copied = ko.observable(undefined),
         folder = ko.observable(ko.mapping.fromJS({children: []})),
-        scrollable = $('#filebrowser'),
-        cachedData;
+        scrollable = $('#filebrowser');
 
+	ctor.prototype.attached = function() {
+     showContextMenu(false);
+		$('#filebrowser').perfectScrollbar();
+	};
+	
     ctor.prototype.activate = function(settings) {
         this.settings = settings;
-        this.selected = selected;
-        this.hasCopied = ko.computed( function() {
-           return copied() !== undefined;
-        });
-        this.showContextMenu = showContextMenu;
-        this.folder = folder;
-        scrollable.perfectScrollbar();
+		this.selected = selected;
+		this.folder = folder;
+		this.showContextMenu = showContextMenu;
+      this.hasSelectedFolder = ko.computed(function() {
+        return selected() != undefined && selected().type === 'folder';
+      });
+      this.hasCopied = ko.computed( function() {
+        return copied() !== undefined;
+      });
     };
 
-    ctor.prototype.openFile = function(object, event) {
-        var type = arguments[0].extra();
-        http.get(arguments[0].path()).then(function(response) {
-	        app.trigger('filebrowser:open_file', {
-	        	type: type,
-	        	content: response
-	        });
-	   });
-    };
+    ctor.prototype.open = function(object,event) {
+    	console.log('Opening', object);
+    	if( object.type() === 'folder' ) {
+	        var id = object.uuid(),
+	        	checkbox = $('input[type=checkbox][id=' + id + ']');
+	        	
+	        checkbox.prop('checked', !checkbox.prop('checked'));
+	        $('#icon_folder_' + id).toggleClass('fa-folder-o').toggleClass('fa-folder-open-o');
+	        
+	        $('#filebrowser').perfectScrollbar('update');
+		} else {
+ 			var type = object.extra();
+	        http.get(object.path()).then(function(response) {
+		        app.trigger('filebrowser:open_file', {
+		        	type: type,
+		        	content: response
+		        });
+		   });
+		}
+    };
     
     ctor.prototype.select = function(object, event) {
-        if( !event.ctrlKey ) {
-            $('li > span.select').removeClass('select');
-            selected.removeAll();
-        }
+        $('li > span.select').removeClass('select');
         $(event.target).toggleClass('select');
-        selected.push( ko.mapping.fromJS(object) );
-    };
-    ctor.prototype.openFolder = function(event) {
-        var id = arguments[0].uuid();
-    	console.log('openFolder', id);
-        $('input[type=checkbox][id=' + id + ']').click();
-        $('#icon_folder_' + id).toggleClass('fa-folder-o').toggleClass('fa-folder-open-o');
-        $('#filebrowser').perfectScrollbar('update');
+        selected( ko.mapping.fromJS(object) );
     };
     
     /** Context Menu **/
 
-    ctor.prototype.openContextMenu = function(object, event) {
-        console.log('openContextMenu');
-        selected( ko.mapping.fromJS(object) );
+    ctor.prototype.openContextMenu = function(object, event) {
         // Position du menu, calculer la pos pour eviter sortie du viewport
         var posX = event.pageX,
             posY = event.pageY,
@@ -76,18 +81,19 @@ define(['durandal/app', 'durandal/composition', 'plugins/http',
             menuWidth = contextMenu.width(),
             menuHeight = contextMenu.height();
 
-        posX = Math.min(posX - 45, windowWidth - menuWidth - 15);
-        posY = Math.min(posY - 80, windowHeight - menuHeight - 10);
+			posX = Math.min(posX, windowWidth - menuWidth - 15);
+			posY = Math.min(posY, windowHeight - menuHeight - 10);
 
-        // display
+        // affichage
         contextMenu.css({
             left : posX + 'px',
             top : posY + 'px'
         });
 
-        showContextMenu(true);
+      
+       showContextMenu(true);
     };
-
+	
     ctor.prototype.openRenamePopup = function(ctor, event) {
         RenameModal.show(ctor.selected().name()).then(function(response) {
             if( response !== undefined ) {
@@ -127,15 +133,15 @@ define(['durandal/app', 'durandal/composition', 'plugins/http',
         });
     };
 
-    $(document).on('click', function() {
+   $(document).on('click', function() {
         showContextMenu(false);
     });
     /** End of Context Menu */
 
   	http.get('/data/filesystem.json').then(function(response) {
         folder(ko.mapping.fromJS(response));
-        $('#filebrowser').perfectScrollbar();
+        $('#filebrowser').perfectScrollbar('update');
    });
-
+
     return ctor;
 });

+ 5 - 5
bower.json

@@ -1,5 +1,5 @@
 {
-  "name": "filebrowser-durandal-widget",
+  "name": "filebrowser-durandal-widget",
   "version": "0.0.1-SNAPSHOT",
   "dependencies" : {
     "durandal" 					: "~2.1.0",
@@ -7,9 +7,9 @@
     "bower-knockout-mapping"	: "~2.5.0",
     "perfect-scrollbar"			: "~0.6.0",
     "bootstrap"					: "~3.3.4",
-    "fontawesome"				: "~4.3.0",
-    "less.js"					: "~2.4.0",
-    "lesshat"					: "~3.0.2",
-    "highlightjs"				: "~8.4.0"
+    "fontawesome"					: "~4.3.0",
+    "less.js"						: "~2.4.0",
+    "lesshat"						: "~3.0.2",
+    "highlightjs"					: "~8.4.0"
   }
 }

+ 125 - 118
data/filesystem.json

@@ -3,89 +3,89 @@
    "name":"workspace",
    "type":"folder",
    "children":[
-      {
-         "uuid":"app",
-         "name":"app",
-         "type":"folder",
-         "children":[
-		      {
-		         "uuid":"widgets",
-		         "name":"widgets",
-		         "type":"folder",
-		         "children":[
-		         	{
-		         		"uuid":"filebrowser",
-		         		"name":"filebrowser",
-		         		"type":"folder",
-		         		"children": [
-			         		{
-				               "name":"newItemModal.html",
-				               "uuid":"newItemModalhtml",
-				               "type":"code",
-				               "extra":"html",
-				               "path": "/app/widgets/filebrowser/newItemModal.html"
-				            },
-			         		{
-				               "name":"newItemModal.js",
-				               "uuid":"newItemModaljs",
-				               "type":"code",
-				               "extra":"javascript",
-				               "path": "/app/widgets/filebrowser/newItemModal.js"
-				            },
-			         		{
-				               "name":"renameModal.html",
-				               "uuid":"renameModalhtml",
-				               "type":"code",
-				               "extra":"html",
-				               "path": "/app/widgets/filebrowser/renameModal.html"
-				            },
-			         		{
-				               "name":"renameModal.js",
-				               "uuid":"renameModaljs",
-				               "type":"code",
-				               "extra":"javascript",
-				               "path": "/app/widgets/filebrowser/renameModal.js"
-				            },
-			         		{
-				               "name":"view.html",
-				               "uuid":"viewhtml",
-				               "type":"code",
-				               "extra":"html",
-				               "path": "/app/widgets/filebrowser/view.html"
-				            },
-			         		{
-				               "name":"viewmodel.js",
-				               "uuid":"viewmodeljs",
-				               "type":"code",
-				               "extra":"javascript",
-				               "path": "/app/widgets/filebrowser/viewmodel.js"
-				            }
-		         		]
-		         	}
-		         ]
-		      },
-		      {
-	               "name":"main.js",
-	               "uuid":"mainjs",
-	               "type":"code",
-	               "extra":"javascript",
-				   "path": "/app/main.js"
-	            },
-	            {
-	               "name":"shell.html",
-	               "uuid":"shellhtml",
-	               "type":"code",
-	               "extra":"html",
-				   "path": "/app/shell.html"
-	            },
-	            {
-	               "name":"shell.js",
-	               "uuid":"shelljs",
-	               "type":"code",
-	               "extra":"javascript",
-				   "path": "/app/shell.js"
-	            }
-         ]
+      {
+         "uuid":"app",
+         "name":"app",
+         "type":"folder",
+         "children":[
+		      {
+		         "uuid":"widgets",
+		         "name":"widgets",
+		         "type":"folder",
+		         "children":[
+		         	{
+		         		"uuid":"filebrowser",
+		         		"name":"filebrowser",
+		         		"type":"folder",
+		         		"children": [
+			         		{
+				               "name":"newItemModal.html",
+				               "uuid":"newItemModalhtml",
+				               "type":"code",
+				               "extra":"html",
+				               "path": "/app/widgets/filebrowser/newItemModal.html"
+				            },
+			         		{
+				               "name":"newItemModal.js",
+				               "uuid":"newItemModaljs",
+				               "type":"code",
+				               "extra":"javascript",
+				               "path": "/app/widgets/filebrowser/newItemModal.js"
+				            },
+			         		{
+				               "name":"renameModal.html",
+				               "uuid":"renameModalhtml",
+				               "type":"code",
+				               "extra":"html",
+				               "path": "/app/widgets/filebrowser/renameModal.html"
+				            },
+			         		{
+				               "name":"renameModal.js",
+				               "uuid":"renameModaljs",
+				               "type":"code",
+				               "extra":"javascript",
+				               "path": "/app/widgets/filebrowser/renameModal.js"
+				            },
+			         		{
+				               "name":"view.html",
+				               "uuid":"viewhtml",
+				               "type":"code",
+				               "extra":"html",
+				               "path": "/app/widgets/filebrowser/view.html"
+				            },
+			         		{
+				               "name":"viewmodel.js",
+				               "uuid":"viewmodeljs",
+				               "type":"code",
+				               "extra":"javascript",
+				               "path": "/app/widgets/filebrowser/viewmodel.js"
+				            }
+		         		]
+		         	}
+		         ]
+		      },
+		      {
+	               "name":"main.js",
+	               "uuid":"mainjs",
+	               "type":"code",
+	               "extra":"javascript",
+				   "path": "/app/main.js"
+	            },
+	            {
+	               "name":"shell.html",
+	               "uuid":"shellhtml",
+	               "type":"code",
+	               "extra":"html",
+				   "path": "/app/shell.html"
+	            },
+	            {
+	               "name":"shell.js",
+	               "uuid":"shelljs",
+	               "type":"code",
+	               "extra":"javascript",
+				   "path": "/app/shell.js"
+	            }
+         ]
       },
       {
          "uuid":"data",
@@ -96,52 +96,59 @@
                "name":"filesystem.json",
                "uuid":"filesystemjson",
                "type":"code",
-               "extra":"json",
+               "extra":"json",
 				"path": "/data/filesystem.json"
             }
          ]
-      },
-      {
-      	"uuid": "style",
-      	"name": "style",
-      	"type": "folder",
-      	"children": [
-      		{
-      			"name": "filebrowser.less",
-      			"uuid": "filebrowserless",
-      			"type": "code",
-      			"extra": "less",
-				"path": "/style/filebrowser.less"
-      		},
-      		{
-      			"name": "starterkit.css",
-      			"uuid": "starterkitcss",
-      			"type": "code",
-      			"extra": "less",
-				"path": "/style/starterkit.css"
-      		}
-      	]
-      },
-      {
+      },
+      {
+      	"uuid": "style",
+      	"name": "style",
+      	"type": "folder",
+      	"children": [
+      		{
+      			"name": "filebrowser.less",
+      			"uuid": "filebrowserless",
+      			"type": "code",
+      			"extra": "less",
+				"path": "/style/filebrowser.less"
+      		},
+      		{
+      			"name": "global.less",
+      			"uuid": "globalless",
+      			"type": "code",
+      			"extra": "less",
+				"path": "/style/global.less"
+      		},
+      		{
+      			"name": "starterkit.css",
+      			"uuid": "starterkitcss",
+      			"type": "code",
+      			"extra": "less",
+				"path": "/style/starterkit.css"
+      		}
+      	]
+      },
+      {
 	      "uuid": "bowerrc",
 	      "name": ".bowerrc",
-	      "type": "code",
-	      "extra": "json",
-	      "path": "/.bowerrc"
+	      "type": "code",
+	      "extra": "json",
+	      "path": "/.bowerrc"
 	  },
-      {
+      {
 	      "uuid": "bowerjson",
 	      "name": "bower.json",
-	      "type": "code",
-	      "extra": "json",
-	      "path": "/bower.json"
+	      "type": "code",
+	      "extra": "json",
+	      "path": "/bower.json"
 	  },
-      {
+      {
 	      "uuid": "indexhtml",
 	      "name": "index.html",
-	      "type": "code",
-	      "extra": "html",
-	      "path": "/index.html"
+	      "type": "code",
+	      "extra": "html",
+	      "path": "/index.html"
 	  }
    ]
 }

+ 11 - 5
index.html

@@ -5,9 +5,9 @@
 		<link rel="stylesheet" href="lib/fontawesome/css/font-awesome.css"/>
 		<link rel="stylesheet" href="lib/durandal/css/durandal.css"/>
 		<link rel="stylesheet" href="lib/perfect-scrollbar/css/perfect-scrollbar.css" />
-		<link rel="stylesheet" href="lib/highlightjs/styles/github.css" />
-		  
+		<link rel="stylesheet" href="lib/highlightjs/styles/github.css" />
 		<link rel="stylesheet" href="style/starterkit.css" />
+		<link rel="stylesheet/less" href="style/global.less" />
 		<link rel="stylesheet/less" href="style/filebrowser.less" />
 	 
 		<script>
@@ -24,7 +24,7 @@
 					<a class="navbar-brand" href="#">Filebrowser Durandal Widget</a>             	
 				</div>
 			</div>
-		</nav>
+		</nav>
 		
 		<div id="applicationHost">
 			<div class="splash">
@@ -32,8 +32,14 @@
 				<i class="fa fa-spinner fa-2x fa-spin active"></i>
 			</div>
 		</div>
-	
-		<script src="lib/requirejs/require.js" data-main="app/main"></script>
+		
+		<nav class="navbar navbar-default navbar-fixed-bottom">
+			<div class="container">
+				Footer
+			</div>
+		</nav>
+		
+		<script src="lib/requirejs/require.js" data-main="app/main"></script>
 		
 	</body>
 </html>

+ 7 - 9
style/filebrowser.less

@@ -1,8 +1,7 @@
 @import "../lib/lesshat/build/lesshat.less";
 
-.filebrowser {
+#filebrowser {
 	max-height: 500px;
-
 	
 	position: relative;
 	
@@ -10,8 +9,6 @@
 	white-space: nowrap;
 }
 
-//http://codepen.io/joshnh/pen/Hkqxu
-//http://codepen.io/tevko/pen/DdsnK
 .folder {
 	
 	& > label {
@@ -50,9 +47,10 @@ ul {
 };
 
 #fileBrowserContextMenu {
-	position: absolute;
-}
-
-.validationMessage {
-	color: red;
+	position: fixed;
+  z-index: 9999;
+}
+
+.validationMessage {
+	color: red;
 }

+ 9 - 0
style/global.less

@@ -0,0 +1,9 @@
+body { 
+	padding-bottom: 100px; 
+}
+
+#editor {
+	position: relative;
+	
+	overflow: hidden;
+}