* This is a special jqLite.replaceWith, which can replace items which * have no parents, provided that the containing jqLite collection is provided. * * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes * i
($rootElement, elementsToRemove, newNode)
| 8565 | * @param {Node} newNode The new DOM node. |
| 8566 | */ |
| 8567 | function replaceWith($rootElement, elementsToRemove, newNode) { |
| 8568 | var firstElementToRemove = elementsToRemove[0], |
| 8569 | removeCount = elementsToRemove.length, |
| 8570 | parent = firstElementToRemove.parentNode, |
| 8571 | i, ii; |
| 8572 | |
| 8573 | if ($rootElement) { |
| 8574 | for (i = 0, ii = $rootElement.length; i < ii; i++) { |
| 8575 | if ($rootElement[i] == firstElementToRemove) { |
| 8576 | $rootElement[i++] = newNode; |
| 8577 | for (var j = i, j2 = j + removeCount - 1, |
| 8578 | jj = $rootElement.length; |
| 8579 | j < jj; j++, j2++) { |
| 8580 | if (j2 < jj) { |
| 8581 | $rootElement[j] = $rootElement[j2]; |
| 8582 | } else { |
| 8583 | delete $rootElement[j]; |
| 8584 | } |
| 8585 | } |
| 8586 | $rootElement.length -= removeCount - 1; |
| 8587 | |
| 8588 | // If the replaced element is also the jQuery .context then replace it |
| 8589 | // .context is a deprecated jQuery api, so we should set it only when jQuery set it |
| 8590 | // http://api.jquery.com/context/ |
| 8591 | if ($rootElement.context === firstElementToRemove) { |
| 8592 | $rootElement.context = newNode; |
| 8593 | } |
| 8594 | break; |
| 8595 | } |
| 8596 | } |
| 8597 | } |
| 8598 | |
| 8599 | if (parent) { |
| 8600 | parent.replaceChild(newNode, firstElementToRemove); |
| 8601 | } |
| 8602 | |
| 8603 | // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it? |
| 8604 | var fragment = document.createDocumentFragment(); |
| 8605 | fragment.appendChild(firstElementToRemove); |
| 8606 | |
| 8607 | if (jqLite.hasData(firstElementToRemove)) { |
| 8608 | // Copy over user data (that includes Angular's $scope etc.). Don't copy private |
| 8609 | // data here because there's no public interface in jQuery to do that and copying over |
| 8610 | // event listeners (which is the main use of private data) wouldn't work anyway. |
| 8611 | jqLite(newNode).data(jqLite(firstElementToRemove).data()); |
| 8612 | |
| 8613 | // Remove data of the replaced element. We cannot just call .remove() |
| 8614 | // on the element it since that would deallocate scope that is needed |
| 8615 | // for the new node. Instead, remove the data "manually". |
| 8616 | if (!jQuery) { |
| 8617 | delete jqLite.cache[firstElementToRemove[jqLite.expando]]; |
| 8618 | } else { |
| 8619 | // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after |
| 8620 | // the replaced element. The cleanData version monkey-patched by Angular would cause |
| 8621 | // the scope to be trashed and we do need the very same scope to work with the new |
| 8622 | // element. However, we cannot just cache the non-patched version and use it here as |
| 8623 | // that would break if another library patches the method after Angular does (one |
| 8624 | // example is jQuery UI). Instead, set a flag indicating scope destroying should be |
no outgoing calls
no test coverage detected