|
| 1 | +(function(){ |
| 2 | + 'use strict'; |
| 3 | + /** |
| 4 | + * @ngdoc overview |
| 5 | + * @name ui.grid.directive:uiGridOneBind |
| 6 | + * @summary A group of directives that provide a one time bind to a dom element. |
| 7 | + * @description A group of directives that provide a one time bind to a dom element. |
| 8 | + * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability. |
| 9 | + * This is done to reduce the number of watchers on the dom. |
| 10 | + * <br/> |
| 11 | + * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2> |
| 12 | + * <pre> |
| 13 | + <div ng-init="imageName = 'myImageDir.jpg'"> |
| 14 | + <img ui-grid-one-bind-src="imageName"></img> |
| 15 | + </div> |
| 16 | + </pre> |
| 17 | + * Will become: |
| 18 | + * <pre> |
| 19 | + <div ng-init="imageName = 'myImageDir.jpg'"> |
| 20 | + <img ui-grid-one-bind-src="imageName" src="myImageDir.jpg"></img> |
| 21 | + </div> |
| 22 | + </pre> |
| 23 | + </br> |
| 24 | + <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2> |
| 25 | + * <pre> |
| 26 | + <div ng-init="text='Add this text'" ui-grid-one-bind-text="text"></div> |
| 27 | + </pre> |
| 28 | + * Will become: |
| 29 | + * <pre> |
| 30 | + <div ng-init="text='Add this text'" ui-grid-one-bind-text="text">Add this text</div> |
| 31 | + </pre> |
| 32 | + </br> |
| 33 | + * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid} |
| 34 | + * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives. |
| 35 | + * |
| 36 | + */ |
| 37 | + //https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js |
| 38 | + var oneBinders = angular.module('ui.grid'); |
| 39 | + angular.forEach([ |
| 40 | + /** |
| 41 | + * @ngdoc directive |
| 42 | + * @name ui.grid.directive:uiGridOneBindSrc |
| 43 | + * @memberof ui.grid.directive:uiGridOneBind |
| 44 | + * @element img |
| 45 | + * @restrict A |
| 46 | + * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 47 | + * @description One time binding for the src dom tag. |
| 48 | + * |
| 49 | + */ |
| 50 | + {tag: 'Src', method: 'attr'}, |
| 51 | + /** |
| 52 | + * @ngdoc directive |
| 53 | + * @name ui.grid.directive:uiGridOneBindText |
| 54 | + * @element div |
| 55 | + * @restrict A |
| 56 | + * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 57 | + * @description One time binding for the text dom tag. |
| 58 | + */ |
| 59 | + {tag: 'Text', method: 'text'}, |
| 60 | + /** |
| 61 | + * @ngdoc directive |
| 62 | + * @name ui.grid.directive:uiGridOneBindHref |
| 63 | + * @element div |
| 64 | + * @restrict A |
| 65 | + * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 66 | + * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 67 | + */ |
| 68 | + {tag: 'Href', method: 'attr'}, |
| 69 | + /** |
| 70 | + * @ngdoc directive |
| 71 | + * @name ui.grid.directive:uiGridOneBindClass |
| 72 | + * @element div |
| 73 | + * @restrict A |
| 74 | + * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 75 | + * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed. |
| 76 | + * this is to prevent the watcher from being removed before the scope is initialized. |
| 77 | + * @param {Array} uiGridOneBindClass An array of classes to bind to this element. |
| 78 | + * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 79 | + */ |
| 80 | + {tag: 'Class', method: 'addClass'}, |
| 81 | + /** |
| 82 | + * @ngdoc directive |
| 83 | + * @name ui.grid.directive:uiGridOneBindHtml |
| 84 | + * @element div |
| 85 | + * @restrict A |
| 86 | + * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 87 | + * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 88 | + */ |
| 89 | + {tag: 'Html', method: 'html'}, |
| 90 | + /** |
| 91 | + * @ngdoc directive |
| 92 | + * @name ui.grid.directive:uiGridOneBindAlt |
| 93 | + * @element div |
| 94 | + * @restrict A |
| 95 | + * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 96 | + * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 97 | + */ |
| 98 | + {tag: 'Alt', method: 'attr'}, |
| 99 | + /** |
| 100 | + * @ngdoc directive |
| 101 | + * @name ui.grid.directive:uiGridOneBindStyle |
| 102 | + * @element div |
| 103 | + * @restrict A |
| 104 | + * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 105 | + * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 106 | + */ |
| 107 | + {tag: 'Style', method: 'css'}, |
| 108 | + /** |
| 109 | + * @ngdoc directive |
| 110 | + * @name ui.grid.directive:uiGridOneBindValue |
| 111 | + * @element div |
| 112 | + * @restrict A |
| 113 | + * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 114 | + * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 115 | + */ |
| 116 | + {tag: 'Value', method: 'attr'}, |
| 117 | + /** |
| 118 | + * @ngdoc directive |
| 119 | + * @name ui.grid.directive:uiGridOneBindId |
| 120 | + * @element div |
| 121 | + * @restrict A |
| 122 | + * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 123 | + * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 124 | + */ |
| 125 | + {tag: 'Id', method: 'attr'}, |
| 126 | + /** |
| 127 | + * @ngdoc directive |
| 128 | + * @name ui.grid.directive:uiGridOneBindIdGrid |
| 129 | + * @element div |
| 130 | + * @restrict A |
| 131 | + * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 132 | + * @description One time binding for the id dom tag. |
| 133 | + * <h1>Important Note!</h1> |
| 134 | + * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring |
| 135 | + * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value. |
| 136 | + * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error. |
| 137 | + * This is done in order to ensure uniqueness of id tags across the grid. |
| 138 | + * This is to prevent two grids in the same document having duplicate id tags. |
| 139 | + */ |
| 140 | + {tag: 'Id', directiveName:'IdGrid', method: 'attr', appendGridId: true}, |
| 141 | + /** |
| 142 | + * @ngdoc directive |
| 143 | + * @name ui.grid.directive:uiGridOneBindTitle |
| 144 | + * @element div |
| 145 | + * @restrict A |
| 146 | + * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 147 | + * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 148 | + */ |
| 149 | + {tag: 'Title', method: 'attr'}, |
| 150 | + /** |
| 151 | + * @ngdoc directive |
| 152 | + * @name ui.grid.directive:uiGridOneBindAriaLabel |
| 153 | + * @element div |
| 154 | + * @restrict A |
| 155 | + * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 156 | + * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 157 | + *<br/> |
| 158 | + * <pre> |
| 159 | + <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text"></div> |
| 160 | + </pre> |
| 161 | + * Will become: |
| 162 | + * <pre> |
| 163 | + <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text" aria-label="Add this text"></div> |
| 164 | + </pre> |
| 165 | + */ |
| 166 | + {tag: 'Label', method: 'attr', aria:true}, |
| 167 | + /** |
| 168 | + * @ngdoc directive |
| 169 | + * @name ui.grid.directive:uiGridOneBindAriaLabelledby |
| 170 | + * @element div |
| 171 | + * @restrict A |
| 172 | + * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 173 | + * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 174 | + *<br/> |
| 175 | + * <pre> |
| 176 | + <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId"></div> |
| 177 | + </pre> |
| 178 | + * Will become: |
| 179 | + * <pre> |
| 180 | + <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId" aria-labelledby="gridID32"></div> |
| 181 | + </pre> |
| 182 | + */ |
| 183 | + {tag: 'Labelledby', method: 'attr', aria:true}, |
| 184 | + /** |
| 185 | + * @ngdoc directive |
| 186 | + * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid |
| 187 | + * @element div |
| 188 | + * @restrict A |
| 189 | + * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>. |
| 190 | + * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}. |
| 191 | + * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the |
| 192 | + * grid id to each one. |
| 193 | + *<br/> |
| 194 | + * <pre> |
| 195 | + <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId"></div> |
| 196 | + </pre> |
| 197 | + * Will become ([grid.id] will be replaced by the actual grid id): |
| 198 | + * <pre> |
| 199 | + <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId" aria-labelledby-Grid="[grid.id]-gridID32"></div> |
| 200 | + </pre> |
| 201 | + */ |
| 202 | + {tag: 'Labelledby', directiveName:'LabelledbyGrid', appendGridId:true, method: 'attr', aria:true}], |
| 203 | + function(v){ |
| 204 | + |
| 205 | + var baseDirectiveName = 'uiGridOneBind'; |
| 206 | + //If it is an aria tag then append the aria label seperately |
| 207 | + //This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it. |
| 208 | + //If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't match up. |
| 209 | + var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag); |
| 210 | + oneBinders.directive(directiveName, ['gridUtil', function(gridUtil){ |
| 211 | + return { |
| 212 | + restrict: 'A', |
| 213 | + require: ['?uiGrid','?^uiGrid'], |
| 214 | + link: function(scope, iElement, iAttrs, controllers){ |
| 215 | + /* Appends the grid id to the beginnig of the value. */ |
| 216 | + var appendGridId = function(val){ |
| 217 | + var grid; //Get an instance of the grid if its available |
| 218 | + //If its available in the scope then we don't need to try to find it elsewhere |
| 219 | + if (scope.grid) { |
| 220 | + grid = scope.grid; |
| 221 | + } |
| 222 | + //Another possible location to try to find the grid |
| 223 | + else if (scope.col && scope.col.grid){ |
| 224 | + grid = scope.col.grid; |
| 225 | + } |
| 226 | + //Last ditch effort: Search through the provided controllers. |
| 227 | + else if (!controllers.some( //Go through the controllers till one has the element we need |
| 228 | + function(controller){ |
| 229 | + if (controller && controller.grid) { |
| 230 | + grid = controller.grid; |
| 231 | + return true; //We've found the grid |
| 232 | + } |
| 233 | + })){ |
| 234 | + //We tried our best to find it for you |
| 235 | + gridUtil.logError("["+directiveName+"] A valid grid could not be found to bind id. Are you using this directive " + |
| 236 | + "within the correct scope? Trying to generate id: [gridID]-" + val); |
| 237 | + throw new Error("No valid grid could be found"); |
| 238 | + } |
| 239 | + |
| 240 | + if (grid){ |
| 241 | + var idRegex = new RegExp(grid.id.toString()); |
| 242 | + //If the grid id hasn't been appended already in the template declaration |
| 243 | + if (!idRegex.test(val)){ |
| 244 | + val = grid.id.toString() + '-' + val; |
| 245 | + } |
| 246 | + } |
| 247 | + return val; |
| 248 | + }; |
| 249 | + |
| 250 | + // The watch returns a function to remove itself. |
| 251 | + var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV){ |
| 252 | + if (newV){ |
| 253 | + //If we are trying to add an id element then we also apply the grid id if it isn't already there |
| 254 | + if (v.appendGridId) { |
| 255 | + var newIdString = null; |
| 256 | + //Append the id to all of the new ids. |
| 257 | + angular.forEach( newV.split(' '), function(s){ |
| 258 | + newIdString = (newIdString ? (newIdString + ' ') : '') + appendGridId(s); |
| 259 | + }); |
| 260 | + newV = newIdString; |
| 261 | + } |
| 262 | + |
| 263 | + // Append this newValue to the dom element. |
| 264 | + switch (v.method) { |
| 265 | + case 'attr': //The attr method takes two paraams the tag and the value |
| 266 | + if (v.aria) { |
| 267 | + //If it is an aria element then append the aria prefix |
| 268 | + iElement[v.method]('aria-' + v.tag.toLowerCase(),newV); |
| 269 | + } else { |
| 270 | + iElement[v.method](v.tag.toLowerCase(),newV); |
| 271 | + } |
| 272 | + break; |
| 273 | + case 'addClass': |
| 274 | + //Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js |
| 275 | + if (angular.isObject(newV) && !angular.isArray(newV)) { |
| 276 | + var results = []; |
| 277 | + var nonNullFound = false; //We don't want to remove the binding unless the key is actually defined |
| 278 | + angular.forEach(newV, function (value, index) { |
| 279 | + if (value !== null && typeof(value) !== "undefined"){ |
| 280 | + nonNullFound = true; //A non null value for a key was found so the object must have been initialized |
| 281 | + if (value) {results.push(index);} |
| 282 | + } |
| 283 | + }); |
| 284 | + //A non null value for a key wasn't found so assume that the scope values haven't been fully initialized |
| 285 | + if (!nonNullFound){ |
| 286 | + return; // If not initialized then the watcher should not be removed yet. |
| 287 | + } |
| 288 | + newV = results; |
| 289 | + } |
| 290 | + |
| 291 | + if (newV) { |
| 292 | + iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV); |
| 293 | + } else { |
| 294 | + return; |
| 295 | + } |
| 296 | + break; |
| 297 | + default: |
| 298 | + iElement[v.method](newV); |
| 299 | + break; |
| 300 | + } |
| 301 | + |
| 302 | + //Removes the watcher on itself after the bind |
| 303 | + rmWatcher(); |
| 304 | + } |
| 305 | + }); //End rm watchers |
| 306 | + } //End compile function |
| 307 | + }; //End directive return |
| 308 | + } // End directive function |
| 309 | + ]); //End directive |
| 310 | + }); // End angular foreach |
| 311 | +})(); |
0 commit comments