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 = self.element('span'); newElement.attr('ng:bind', exp); } else { newElement = self.text(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(); } } }); // TODO: this should be widget not a markup angularTextMarkup('OPTION', function(text, textNode, parentElement){ if (nodeName(parentElement) == "OPTION") { var select = document.createElement('select'); select.insertBefore(parentElement[0].cloneNode(true), _null); if (!select.innerHTML.match(/.*<\/\s*option\s*>/gi)) { 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, ff 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. */ /** * @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. */ var NG_BIND_ATTR = 'ng:bind-attr'; var SPECIAL_ATTRS = {'ng:src': 'src', 'ng:href': 'href'}; 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)); } });