'use strict'; /** * @workInProgress * @ngdoc overview * @name angular.markup * @description * * Angular markup transforms content of DOM elements or portions of this content into other text or * DOM elements for further compilation. * * Markup extensions do not themselves produce linking functions. Think of markup as a way to * produce shorthand for a {@link angular.widget widget} or a {@link angular.directive directive}. * * The most prominent example of a markup in angular is the built-in double curly markup * `{{expression}}`, which is shorthand for ``. * * Create custom markup like this: * *
 *   angular.markup('newMarkup', function(text, textNode, parentElement){
 *     //tranformation code
 *   });
 * 
* * For more information about angular markup, see {@link guide/dev_guide.compiler.markup * Understanding Angular Markup} in the angular Developer Guide. */ /** * @workInProgress * @ngdoc overview * @name angular.attrMarkup * @description * * Attribute markup extends the angular compiler in a very similar way as {@link angular.markup} * except that it allows you to modify the state of the attribute text rather than the content of a * node. * * Create custom attribute markup like this: * *
 *   angular.attrMarkup('newAttrMarkup', function(attrValue, attrName, element){
 *     //tranformation code
 *   });
 * 
* * For more information about angular attribute markup, see {@link guide/dev_guide.compiler.markup * Understanding Angular Markup} in the angular Developer Guide. */ function parseBindings(string) { var results = []; var lastIndex = 0; var index; while((index = string.indexOf('{{', lastIndex)) > -1) { if (lastIndex < index) results.push(string.substr(lastIndex, index - lastIndex)); lastIndex = index; index = string.indexOf('}}', index); index = index < 0 ? string.length : index + 2; results.push(string.substr(lastIndex, index - lastIndex)); lastIndex = index; } if (lastIndex != string.length) results.push(string.substr(lastIndex, string.length - lastIndex)); return results.length === 0 ? [ string ] : results; } function binding(string) { var binding = string.replace(/\n/gm, ' ').match(/^\{\{(.*)\}\}$/); return binding ? binding[1] : null; } function hasBindings(bindings) { return bindings.length > 1 || binding(bindings[0]) !== null; } angularTextMarkup('{{}}', function(text, textNode, parentElement) { var bindings = parseBindings(text), self = this; if (hasBindings(bindings)) { if (isLeafNode(parentElement[0])) { parentElement.attr('ng:bind-template', text); } else { var cursor = textNode, newElement; forEach(parseBindings(text), function(text){ var exp = binding(text); if (exp) { newElement = jqLite(''); newElement.attr('ng:bind', exp); } else { newElement = jqLite(document.createTextNode(text)); } if (msie && text.charAt(0) == ' ') { newElement = jqLite(' '); var nbsp = newElement.html(); newElement.text(text.substr(1)); newElement.html(nbsp + newElement.html()); } cursor.after(newElement); cursor = newElement; }); textNode.remove(); } } }); /** * This tries to normalize the behavior of value attribute across browsers. If value attribute is * not specified, then specify it to be that of the text. */ angularTextMarkup('option', function(text, textNode, parentElement){ if (lowercase(nodeName_(parentElement)) == 'option') { if (msie <= 7) { // In IE7 The issue is that there is no way to see if the value was specified hence // we have to resort to parsing HTML; htmlParser(parentElement[0].outerHTML, { start: function(tag, attrs) { if (isUndefined(attrs.value)) { parentElement.attr('value', text); } } }); } else if (parentElement[0].getAttribute('value') == null) { // jQuery does normalization on 'value' so we have to bypass it. parentElement.attr('value', text); } } }); /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:href * * @description * Using markup like {{hash}} in an href attribute makes * the page open to a wrong URL, if the user clicks that link before * angular has a chance to replace the {{hash}} with actual URL, the * link will be broken and will most likely return a 404 error. * The `ng:href` solves this problem by placing the `href` in the * `ng:` namespace. * * The buggy way to write it: *
 * 
 * 
* * The correct way to write it: *
 * 
 * 
* * @element ANY * @param {template} template any string which can contain `{{}}` markup. * * @example * This example uses `link` variable inside `href` attribute:
link 1 (link, don't reload)
link 2 (link, don't reload)
link 3 (link, reload!)
anchor (link, don't reload)
anchor (no link)
link (link, change hash) it('should execute ng:click but not reload when href without value', function() { element('#link-1').click(); expect(input('value').val()).toEqual('1'); expect(element('#link-1').attr('href')).toBe(""); }); it('should execute ng:click but not reload when href empty string', function() { element('#link-2').click(); expect(input('value').val()).toEqual('2'); expect(element('#link-2').attr('href')).toBe(""); }); it('should execute ng:click and change url when ng:href specified', function() { element('#link-3').click(); expect(input('value').val()).toEqual('3'); expect(element('#link-3').attr('href')).toBe("#123"); expect(browser().location().hash()).toEqual('123'); }); it('should execute ng:click but not reload when href empty string and name specified', function() { element('#link-4').click(); expect(input('value').val()).toEqual('4'); expect(element('#link-4').attr('href')).toBe(""); }); it('should execute ng:click but not reload when no href but name specified', function() { element('#link-5').click(); expect(input('value').val()).toEqual('5'); expect(element('#link-5').attr('href')).toBe(undefined); }); it('should only change url when only ng:href', function() { input('value').enter('6'); element('#link-6').click(); expect(browser().location().hash()).toEqual('/6'); expect(element('#link-6').attr('href')).toBe("#/6"); }); */ /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:src * * @description * Using markup like `{{hash}}` in a `src` attribute doesn't * work right: The browser will fetch from the URL with the literal * text `{{hash}}` until replaces the expression inside * `{{hash}}`. The `ng:src` attribute solves this problem by placing * the `src` attribute in the `ng:` namespace. * * The buggy way to write it: *
 * 
 * 
* * The correct way to write it: *
 * 
 * 
* * @element ANY * @param {template} template any string which can contain `{{}}` markup. */ /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:disabled * * @description * * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: *
 * 
* *
*
* * The HTML specs do not require browsers to preserve the special attributes such as disabled. * (The presence of them means true and absence means false) * This prevents the angular compiler from correctly retrieving the binding expression. * To solve this problem, we introduce ng:disabled. * * @example Click me to toggle:
it('should toggle button', function() { expect(element('.doc-example-live :button').attr('disabled')).toBeFalsy(); input('checked').check(); expect(element('.doc-example-live :button').attr('disabled')).toBeTruthy(); });
* * @element ANY * @param {template} template any string which can contain '{{}}' markup. */ /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:checked * * @description * The HTML specs do not require browsers to preserve the special attributes such as checked. * (The presence of them means true and absence means false) * This prevents the angular compiler from correctly retrieving the binding expression. * To solve this problem, we introduce ng:checked. * @example Check me to check both:
it('should check both checkBoxes', function() { expect(element('.doc-example-live #checkSlave').attr('checked')).toBeFalsy(); input('master').check(); expect(element('.doc-example-live #checkSlave').attr('checked')).toBeTruthy(); });
* * @element ANY * @param {template} template any string which can contain '{{}}' markup. */ /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:multiple * * @description * The HTML specs do not require browsers to preserve the special attributes such as multiple. * (The presence of them means true and absence means false) * This prevents the angular compiler from correctly retrieving the binding expression. * To solve this problem, we introduce ng:multiple. * * @example Check me check multiple:
it('should toggle multiple', function() { expect(element('.doc-example-live #select').attr('multiple')).toBeFalsy(); input('checked').check(); expect(element('.doc-example-live #select').attr('multiple')).toBeTruthy(); });
* * @element ANY * @param {template} template any string which can contain '{{}}' markup. */ /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:readonly * * @description * The HTML specs do not require browsers to preserve the special attributes such as readonly. * (The presence of them means true and absence means false) * This prevents the angular compiler from correctly retrieving the binding expression. * To solve this problem, we introduce ng:readonly. * @example Check me to make text readonly:
it('should toggle readonly attr', function() { expect(element('.doc-example-live :text').attr('readonly')).toBeFalsy(); input('checked').check(); expect(element('.doc-example-live :text').attr('readonly')).toBeTruthy(); });
* * @element ANY * @param {template} template any string which can contain '{{}}' markup. */ /** * @workInProgress * @ngdoc directive * @name angular.directive.ng:selected * * @description * The HTML specs do not require browsers to preserve the special attributes such as selected. * (The presence of them means true and absence means false) * This prevents the angular compiler from correctly retrieving the binding expression. * To solve this problem, we introduce ng:selected. * @example Check me to select:
it('should select Greetings!', function() { expect(element('.doc-example-live #greet').attr('selected')).toBeFalsy(); input('checked').check(); expect(element('.doc-example-live #greet').attr('selected')).toBeTruthy(); });
* @element ANY * @param {template} template any string which can contain '{{}}' markup. */ var NG_BIND_ATTR = 'ng:bind-attr'; var SPECIAL_ATTRS = {}; forEach('src,href,checked,disabled,multiple,readonly,selected'.split(','), function(name) { SPECIAL_ATTRS['ng:' + name] = name; }); angularAttrMarkup('{{}}', function(value, name, element){ // don't process existing attribute markup if (angularDirective(name) || angularDirective("@" + name)) return; if (msie && name == 'src') value = decodeURI(value); var bindings = parseBindings(value), bindAttr; if (hasBindings(bindings)) { element.removeAttr(name); bindAttr = fromJson(element.attr(NG_BIND_ATTR) || "{}"); bindAttr[SPECIAL_ATTRS[name] || name] = value; element.attr(NG_BIND_ATTR, toJson(bindAttr)); } });