Directive cleanup + button event js errors fix

This commit is contained in:
perploug
2014-03-06 12:28:36 +01:00
parent 4aa3e1368a
commit dfaa15c6e7
20 changed files with 338 additions and 409 deletions

View File

@@ -1,59 +0,0 @@
angular.module('umbraco.directives.editors').directive('ace', function(assetsService) {
var ACE_EDITOR_CLASS = 'ace-editor';
function loadAceEditor(element, mode) {
assetsService.loadJs("lib/ace/noconflict/ace.js").then(function(){
var editor = ace.edit($(element).find('.' + ACE_EDITOR_CLASS)[0]);
editor.session.setMode("ace/mode/" + mode);
editor.renderer.setShowPrintMargin(false);
return editor;
});
}
function valid(editor) {
return (Object.keys(editor.getSession().getAnnotations()).length === 0);
}
return {
restrict: 'A',
require: '?ngModel',
transclude: true,
template: '<div class="transcluded" ng-transclude></div><div class="' + ACE_EDITOR_CLASS + '"></div>',
link: function(scope, element, attrs, ngModel) {
function read() {
ngModel.$setViewValue(editor.getValue());
textarea.val(editor.getValue());
}
var textarea = $(element).find('textarea');
textarea.hide();
var mode = attrs.ace;
var editor = loadAceEditor(element, mode);
scope.ace = editor;
if (!ngModel)
{
return; // do nothing if no ngModel
}
ngModel.$render = function() {
var value = ngModel.$viewValue || '';
editor.getSession().setValue(value);
textarea.val(value);
};
editor.getSession().on('changeAnnotation', function() {
if (valid(editor)) {
scope.$apply(read);
}
});
editor.getSession().setValue(textarea.val());
read();
}
};
});

View File

@@ -1,33 +1,33 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbFileUpload
* @function
* @restrict A
* @scope
* @description
* A single file upload field that will reset itself based on the object passed in for the rebuild parameter. This
* is required because the only way to reset an upload control is to replace it's html.
**/
function umbSingleFileUpload($compile) {
return {
restrict: "E",
scope: {
rebuild: "="
},
replace: true,
template: "<div><input type='file' umb-file-upload /></div>",
link: function (scope, el, attrs) {
scope.$watch("rebuild", function (newVal, oldVal) {
if (newVal && newVal !== oldVal) {
//recompile it!
el.html("<input type='file' umb-file-upload />");
$compile(el.contents())(scope);
}
});
}
};
}
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbFileUpload
* @function
* @restrict A
* @scope
* @description
* A single file upload field that will reset itself based on the object passed in for the rebuild parameter. This
* is required because the only way to reset an upload control is to replace it's html.
**/
function umbSingleFileUpload($compile) {
return {
restrict: "E",
scope: {
rebuild: "="
},
replace: true,
template: "<div><input type='file' umb-file-upload /></div>",
link: function (scope, el, attrs) {
scope.$watch("rebuild", function (newVal, oldVal) {
if (newVal && newVal !== oldVal) {
//recompile it!
el.html("<input type='file' umb-file-upload />");
$compile(el.contents())(scope);
}
});
}
};
}
angular.module('umbraco.directives').directive("umbSingleFileUpload", umbSingleFileUpload);

View File

@@ -1,30 +1,30 @@
angular.module("umbraco.directives")
.directive('sectionIcon', function ($compile, iconHelper) {
return {
restrict: 'E',
replace: true,
link: function (scope, element, attrs) {
var icon = attrs.icon;
if (iconHelper.isLegacyIcon(icon)) {
//its a known legacy icon, convert to a new one
element.html("<i class='" + iconHelper.convertFromLegacyIcon(icon) + "'></i>");
}
else if (iconHelper.isFileBasedIcon(icon)) {
var convert = iconHelper.convertFromLegacyImage(icon);
if(convert){
element.html("<i class='icon-section " + convert + "'></i>");
}else{
element.html("<img src='images/tray/" + icon + "'>");
}
//it's a file, normally legacy so look in the icon tray images
}
else {
//it's normal
element.html("<i class='icon-section " + icon + "'></i>");
}
}
};
angular.module("umbraco.directives")
.directive('sectionIcon', function ($compile, iconHelper) {
return {
restrict: 'E',
replace: true,
link: function (scope, element, attrs) {
var icon = attrs.icon;
if (iconHelper.isLegacyIcon(icon)) {
//its a known legacy icon, convert to a new one
element.html("<i class='" + iconHelper.convertFromLegacyIcon(icon) + "'></i>");
}
else if (iconHelper.isFileBasedIcon(icon)) {
var convert = iconHelper.convertFromLegacyImage(icon);
if(convert){
element.html("<i class='icon-section " + convert + "'></i>");
}else{
element.html("<img src='images/tray/" + icon + "'>");
}
//it's a file, normally legacy so look in the icon tray images
}
else {
//it's normal
element.html("<i class='icon-section " + icon + "'></i>");
}
}
};
});

View File

@@ -1,27 +1,27 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbAvatar
* @restrict E
**/
function avatarDirective() {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
templateUrl: 'views/directives/umb-avatar.html',
scope: {
name: '@',
email: '@',
hash: '@'
},
link: function(scope, element, attr, ctrl) {
scope.$watch("hash", function (val) {
//set the gravatar url
scope.gravatar = "http://www.gravatar.com/avatar/" + val + "?s=40";
});
}
};
}
angular.module('umbraco.directives').directive("umbAvatar", avatarDirective);
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbAvatar
* @restrict E
**/
function avatarDirective() {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
templateUrl: 'views/directives/umb-avatar.html',
scope: {
name: '@',
email: '@',
hash: '@'
},
link: function(scope, element, attr, ctrl) {
scope.$watch("hash", function (val) {
//set the gravatar url
scope.gravatar = "http://www.gravatar.com/avatar/" + val + "?s=40";
});
}
};
}
angular.module('umbraco.directives').directive("umbAvatar", avatarDirective);

View File

@@ -1,79 +1,79 @@
angular.module("umbraco.directives")
.directive('umbHeader', function($parse, $timeout){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-header.html',
//create a new isolated scope assigning a tabs property from the attribute 'tabs'
//which is bound to the parent scope property passed in
scope: {
tabs: "="
},
link: function (scope, iElement, iAttrs) {
var maxTabs = 4;
function collectFromDom(activeTab){
var $panes = $('div.tab-content');
angular.forEach($panes.find('.tab-pane'), function (pane, index) {
var $this = angular.element(pane);
var id = $this.attr("rel");
var label = $this.attr("label");
var tab = {id: id, label: label, active: false};
if(!activeTab){
tab.active = true;
activeTab = tab;
}
if ($this.attr("rel") === String(activeTab.id)) {
$this.addClass('active');
}
else {
$this.removeClass('active');
}
if(label){
scope.visibleTabs.push(tab);
}
});
}
scope.showTabs = iAttrs.tabs ? true : false;
scope.visibleTabs = [];
scope.overflownTabs = [];
$timeout(function () {
collectFromDom(undefined);
}, 500);
//when the tabs change, we need to hack the planet a bit and force the first tab content to be active,
//unfortunately twitter bootstrap tabs is not playing perfectly with angular.
scope.$watch("tabs", function (newValue, oldValue) {
angular.forEach(newValue, function(val, index){
var tab = {id: val.id, label: val.label};
scope.visibleTabs.push(tab);
});
//don't process if we cannot or have already done so
if (!newValue) {return;}
if (!newValue.length || newValue.length === 0){return;}
var activeTab = _.find(newValue, function (item) {
return item.active;
});
//we need to do a timeout here so that the current sync operation can complete
// and update the UI, then this will fire and the UI elements will be available.
$timeout(function () {
collectFromDom(activeTab);
}, 500);
});
}
};
angular.module("umbraco.directives")
.directive('umbHeader', function($parse, $timeout){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-header.html',
//create a new isolated scope assigning a tabs property from the attribute 'tabs'
//which is bound to the parent scope property passed in
scope: {
tabs: "="
},
link: function (scope, iElement, iAttrs) {
var maxTabs = 4;
function collectFromDom(activeTab){
var $panes = $('div.tab-content');
angular.forEach($panes.find('.tab-pane'), function (pane, index) {
var $this = angular.element(pane);
var id = $this.attr("rel");
var label = $this.attr("label");
var tab = {id: id, label: label, active: false};
if(!activeTab){
tab.active = true;
activeTab = tab;
}
if ($this.attr("rel") === String(activeTab.id)) {
$this.addClass('active');
}
else {
$this.removeClass('active');
}
if(label){
scope.visibleTabs.push(tab);
}
});
}
scope.showTabs = iAttrs.tabs ? true : false;
scope.visibleTabs = [];
scope.overflownTabs = [];
$timeout(function () {
collectFromDom(undefined);
}, 500);
//when the tabs change, we need to hack the planet a bit and force the first tab content to be active,
//unfortunately twitter bootstrap tabs is not playing perfectly with angular.
scope.$watch("tabs", function (newValue, oldValue) {
angular.forEach(newValue, function(val, index){
var tab = {id: val.id, label: val.label};
scope.visibleTabs.push(tab);
});
//don't process if we cannot or have already done so
if (!newValue) {return;}
if (!newValue.length || newValue.length === 0){return;}
var activeTab = _.find(newValue, function (item) {
return item.active;
});
//we need to do a timeout here so that the current sync operation can complete
// and update the UI, then this will fire and the UI elements will be available.
$timeout(function () {
collectFromDom(activeTab);
}, 500);
});
}
};
});

View File

@@ -9,66 +9,6 @@ angular.module("umbraco.directives.html")
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/html/umb-panel.html',
link: function (scope, el, attrs) {
function _setClass(bar, resize){
bar = $(bar);
//no need to process
if(resize){
bar.removeClass("umb-bottom-bar");
}
//already positioned
if(bar.hasClass("umb-bottom-bar")){
return;
}
var offset = bar.offset();
if(offset){
var bottom = bar.offset().top + bar.height();
if(bottom > $(window).height()){
bar.addClass("umb-bottom-bar");
$(".tab-content .active").addClass("with-buttons");
}else{
bar.removeClass("umb-bottom-bar");
$(".tab-content .active").removeClass("with-buttons");
}
}
}
//initial loading
$timeout(function(){
var bar = $(".tab-content .active .umb-tab-buttons")[0] || $(".tab-content .umb-tab-buttons")[0];
var winHeight = $(window).height();
scope.$watch(function () {
if(!bar){
bar = $(".tab-content .active .umb-tab-buttons")[0] || $(".tab-content .umb-tab-buttons")[0];
}
var bottom = bar.offsetTop + bar.offsetHeight;
return bottom > winHeight;
}, function(val) {
_setClass(bar);
});
$(window).bind("resize", function () {
_setClass(bar, true);
winHeight = $(window).height();
});
$('a[data-toggle="tab"]').on('shown', function (e) {
bar = $(".tab-content .active .umb-tab-buttons")[0];
_setClass(bar);
});
}, 1000, false);
}
templateUrl: 'views/directives/html/umb-panel.html'
};
});

View File

@@ -1,14 +1,14 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbTab
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbTab', function(){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab.html'
};
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbTab
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbTab', function(){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab.html'
};
});

View File

@@ -1,14 +1,14 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbTabView
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbTabView', function($timeout, $log){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab-view.html'
};
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbTabView
* @restrict E
**/
angular.module("umbraco.directives")
.directive('umbTabView', function($timeout, $log){
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab-view.html'
};
});

View File

@@ -1,38 +1,38 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:autoScale
* @element div
* @function
*
* @description
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
*
* @example
<example module="umbraco.directives">
<file name="index.html">
<div auto-scale="70" class="input-block-level"></div>
</file>
</example>
*/
angular.module("umbraco.directives")
.directive('autoScale', function ($window) {
return function (scope, el, attrs) {
var totalOffset = 0;
var offsety = parseInt(attrs.autoScale, 10);
var window = angular.element($window);
if (offsety !== undefined){
totalOffset += offsety;
}
setTimeout(function () {
el.height(window.height() - (el.offset().top + totalOffset));
}, 500);
window.bind("resize", function () {
el.height(window.height() - (el.offset().top + totalOffset));
});
};
/**
* @ngdoc directive
* @name umbraco.directives.directive:autoScale
* @element div
* @function
*
* @description
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
*
* @example
<example module="umbraco.directives">
<file name="index.html">
<div auto-scale="70" class="input-block-level"></div>
</file>
</example>
*/
angular.module("umbraco.directives")
.directive('autoScale', function ($window) {
return function (scope, el, attrs) {
var totalOffset = 0;
var offsety = parseInt(attrs.autoScale, 10);
var window = angular.element($window);
if (offsety !== undefined){
totalOffset += offsety;
}
setTimeout(function () {
el.height(window.height() - (el.offset().top + totalOffset));
}, 500);
window.bind("resize", function () {
el.height(window.height() - (el.offset().top + totalOffset));
});
};
});

View File

@@ -0,0 +1,49 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbPanel
* @restrict E
**/
angular.module("umbraco.directives.html")
.directive('detectFold', function($timeout, $log){
return {
restrict: 'A',
link: function (scope, el, attrs) {
var state = false,
parent = $(".umb-panel-body"),
winHeight = $(window).height(),
calculate = _.throttle(function(){
if(el && el.is(":visible") && !el.hasClass("umb-bottom-bar")){
//var parent = el.parent();
var hasOverflow = parent.innerHeight() < parent[0].scrollHeight;
//var belowFold = (el.offset().top + el.height()) > winHeight;
if(hasOverflow){
el.addClass("umb-bottom-bar");
}
}
return state;
}, 1000);
scope.$watch(calculate, function(newVal, oldVal) {
if(newVal !== oldVal){
if(newVal){
el.addClass("umb-bottom-bar");
}else{
el.removeClass("umb-bottom-bar");
}
}
});
$(window).bind("resize", function () {
winHeight = $(window).height();
el.removeClass("umb-bottom-bar");
state = false;
calculate();
});
$('a[data-toggle="tab"]').on('shown', function (e) {
calculate();
});
}
};
});

View File

@@ -1,27 +1,27 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:headline
**/
angular.module("umbraco.directives")
.directive('hotkey', function ($window, keyboardService, $log) {
return function (scope, el, attrs) {
//support data binding
var keyCombo = scope.$eval(attrs["hotkey"]);
if (!keyCombo) {
keyCombo = attrs["hotkey"];
}
keyboardService.bind(keyCombo, function() {
var element = $(el);
if(element.is("a,button,input[type='button'],input[type='submit']")){
element.click();
}else{
element.focus();
}
});
};
/**
* @ngdoc directive
* @name umbraco.directives.directive:headline
**/
angular.module("umbraco.directives")
.directive('hotkey', function ($window, keyboardService, $log) {
return function (scope, el, attrs) {
//support data binding
var keyCombo = scope.$eval(attrs["hotkey"]);
if (!keyCombo) {
keyCombo = attrs["hotkey"];
}
keyboardService.bind(keyCombo, function() {
var element = $(el);
if(element.is("a,button,input[type='button'],input[type='submit']")){
element.click();
}else{
element.focus();
}
});
};
});

View File

@@ -1,29 +1,29 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:preventDefault
**/
angular.module("umbraco.directives")
.directive('preventDefault', function() {
return function(scope, element, attrs) {
var enabled = true;
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
//prevent default.
if (attrs.preventDefault) {
attrs.$observe("preventDefault", function (newVal) {
enabled = (newVal === "false" || newVal === 0 || newVal === false) ? false : true;
});
}
$(element).click(function (event) {
if (event.metaKey || event.ctrlKey) {
return;
}
else {
if (enabled === true) {
event.preventDefault();
}
}
});
};
/**
* @ngdoc directive
* @name umbraco.directives.directive:preventDefault
**/
angular.module("umbraco.directives")
.directive('preventDefault', function() {
return function(scope, element, attrs) {
var enabled = true;
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
//prevent default.
if (attrs.preventDefault) {
attrs.$observe("preventDefault", function (newVal) {
enabled = (newVal === "false" || newVal === 0 || newVal === false) ? false : true;
});
}
$(element).click(function (event) {
if (event.metaKey || event.ctrlKey) {
return;
}
else {
if (enabled === true) {
event.preventDefault();
}
}
});
};
});

View File

@@ -166,7 +166,7 @@
}
.umb-tab-buttons{padding-left: 240px;}
.umb-tab-pane.with-buttons{padding-bottom: 90px}
.umb-tab-pane{padding-bottom: 90px}
.tab-content{overflow: visible; }

View File

@@ -38,8 +38,7 @@
</umb-property>
<div class="umb-tab-buttons" ng-class="{'umb-dimmed': busy}">
<div class="umb-tab-buttons" detect-fold ng-class="{'umb-dimmed': busy}">
<div class="btn-group" ng-show="content.template">
<a class="btn" ng-click="preview(content)">
<localize key="buttons_showPage">Preview page</localize>

View File

@@ -53,7 +53,7 @@
</umb-property>
<div class="umb-tab-buttons">
<div class="umb-tab-buttons" detect-fold>
<div class="btn-group">
<button type="submit" data-hotkey="ctrl+s" class="btn btn-success">
<localize key="buttons_save">Save</localize>

View File

@@ -37,7 +37,7 @@
<umb-editor model="property"></umb-editor>
</umb-property>
<div class="umb-tab-buttons" ng-class="{'umb-dimmed': busy}">
<div class="umb-tab-buttons" detect-fold ng-class="{'umb-dimmed': busy}">
<div class="btn-group">
<button type="submit" data-hotkey="ctrl+s" class="btn btn-success">
<localize key="buttons_save">Save</localize>

View File

@@ -37,7 +37,7 @@
<umb-editor model="property"></umb-editor>
</umb-property>
<div class="umb-tab-buttons" ng-class="{'umb-dimmed': busy}">
<div class="umb-tab-buttons" detect-fold ng-class="{'umb-dimmed': busy}">
<div class="btn-group">
<button type="submit" data-hotkey="ctrl+s" class="btn btn-success">
<localize key="buttons_save">Save</localize>