Turn an anchor into a span? - javascript

What's the easiest way to turn an <a> into <span> keeping all the attributes and content? (except for perhaps the href).
.replaceWith() replaces the whole shebang.

You can iterate an element's attributes using the attributes property. You can copy an attribute using attribute.cloneNode(true). You can add that cloned attribute to another element's attributes collection with element.attributes.setNamedItem(attribute).
Here's a quick plugin that does it:
$.fn.cloneTo = function (target) {
// copies the attributes, html, and event handlers of the first element to each of
// the elements in the provided jQuery object or that match the provided selector
if (!target || !target.jquery) {
target = $(target);
}
if (this.length) {
$.each(this[0].attributes, function(i, attr) {
target.each(function(){
this.attributes.setNamedItem(attr.cloneNode(true));
});
});
$.each(this.data("events"), function(evt, handlers){
$.each(handlers, function(i, handler){
target.bind(evt, handler);
});
});
target.empty().append(this.contents());
}
return this;
};
Use it like this:
var span = $("<span>");
$("#myLink").cloneTo(span).replaceWith(span);
Working demo: http://jsfiddle.net/gLqZJ/2
Edit: Updated above to copy event handlers and to keep the descendent nodes untouched, rather than duplicating the HTML.

How about
$element.html(function(html) {
return html.replace(/<(\/?)a/gi, "<$1span"); // string manipulation might be faster, but you get the concept
});
That would save the attributes and content, but not any data and event handlers. If you need those for the descendants, you should remove the child nodes and append them to the new span.
EDIT: Sorry, I'm not that familiar with jQuery. The .html() method changes the innerHTML, not including the node itself. The function should be something like:
$element(s).each(function() {
var l = this.tagName.length + 1;
this.outerHTML = "<span"+this.outerHTML.slice(l, -l)+"span>";
});

Combine jQuery's replaceWith() and html() and copy attributes iteratively. Given your anchor tag has id #anchor:
$('#anchor').replaceWith(function() {
var span = $('<span/>');
$.each(this.attributes, function(){
span.attr(this.name, this.value);
});
return span.html($(this).html());
});
See updated jsFiddle for an example.

Related

Move array of DOM elements to placeholders in page

I have a design received on my page with a set of placeholders such as:
<span id="ApplicationDate_" class="removeMe"></span>
Plus other many elements as well inside that html. These spans should be replaced by real inputs coming from another area on the page, such inputs look like:
<input type="text" id="ApplicationDate_48596977"/>
So basically what I need to do, is to get all input elements in an array, and then for each element, get its ID up to "_", and search for the span that equals that value, and replace it with this element, then remove all spans with class=removeMe, but I can't achieve it in code, below is what I have reached:
$(document).ready(function () {
var coll = $("input");
coll.each(function () {
var id = this.id; //getting the id here
var substringId = id.substring(0, id.indexOf('_') + 1); //getting the span id
this.appendTo("#" + substringId); //having problems here..
});
$(".removeMe").each(function () {
this.remove();
});
});
it tells me this.appendTo is not a function, any help or hint is much appreciated.
TL;DR - Just use:
$(".removeMe").replaceWith(function() {
return $("input[id^='" + this.id + "']");
});
Here's why:
this is a DOM element, but .appendTo() is a jQuery method. You probably just need to wrap this in a call to jQuery:
$(this).appendTo("#" + substringId);
That would place the <input> element inside the <span> like this:
<span id="ApplicationDate_" class="removeMe">
<input type="text" id="ApplicationDate_48596977"/>
</span>
But, then you call:
$(".removeMe").each(function () {
this.remove();
});
First, you would have the same problem as above - this is a DOM element, but .remove() is a jQuery method. Second, it would be better to just call $(".removeMe").remove() - wrapping it in a .each() is redundant. Third, that would remove the span, and the input along with it. That's not what you are trying to do is it?
If you want to replace the span with the input, use .replaceWith():
var coll = $("input");
coll.each(function () {
var substringId = this.id.substring(0, id.indexOf('_') + 1);
$("#" + substringId).replaceWith(this);
});
It seems like the whole thing could be rewritten, taking advantage of the attribute starts with selector, as:
$(".removeMe").replaceWith(function() {
return $("input[id^='" + this.id + "']");
});

JavaScript get h1 elements in HTML document and update unique IDs

I have a legacy html document containing h1 elements which don't have ids.
What I would like to achieve is to be able, using JavaScript, to get all h1(s) and then add to each a unique ID.
I have searched but could not find a solution that works.
Try getting all of them with document.getElementsByTagName("h1"). Loop through them, check if they have an id, and work appropriately. Try:
var h1s = document.getElementsByTagName("h1");
for (var i = 0; i < h1s.length; i++) {
var h1 = h1s[i];
if (!h1.id) {
h1.id = "h1" + i + (new Date().getTime());
}
}
DEMO: http://jsfiddle.net/kTvA2/
After running the demo, if you inspect the DOM, you'll see 3 out of the 4 h1 elements have a new, unique id. The one with the id in the first place isn't changed.
Note that this code needs to run after all elements are ready/rendered, which can be achieved by putting the code inside of a window.onload handler. The demo provided is set up to implicitly run the code then.
UPDATE:
With jQuery, you could use:
$(document).ready(function () {
$("h1:not([id])").attr("id", function (i, attr) {
return "h1" + i + (new Date().getTime());
});
});
DEMO: http://jsfiddle.net/kTvA2/7/
Use querySelectorAll() to get all of your header elements, then iterate over the result and generate yor unique id for each element.
var headerElements = document.querySelectorAll('h1');
for(h in headerElements) {
if(headerElements[h] instanceof Element) {
headerElements[h].id=uniqueIDgenerator();
}
}

How to append an element, all its children, and all classes of the parent and children with jQuery

I have a function that is successful in removing an element and appending it elsewhere on the page as successful. The problem is that as soon as the document is ready jQuery adds classes and attributes to the children that upon moving are lost. I need these classes and attributes to remain after removing and appending. I have thought about calling the original function that adds the classes, but the problem is they are key based and rely on their position prior to the move, calling it after changes the key and thus will add brand new and different classes.
The classes adding jQuery is pretty standard:
$(function(){
$("div").each(function(key){
if ($(this).hasClass("container")){
$(this).find("ul").addClass("parent" + key);
$(this).find(".container-item").attr("parentClass", ".parent" + key);
};
});
});
The remove/append function:
function copy_item(draggable, target){
var account = clone_items(draggable);
//$('#'+name.uid).remove();
$('#'+name.uid).hide();
target.append(make_div(name, true, true));
//$(draggable).children().attr("class", ($(draggable).children().attr("class")));
}
function make_div(name, drag, drop){
var newdiv = document.createElement('div');
newdiv.setAttribute('id', name.uid);
newdiv.appendChild(make_h3(name.username));
ul = document.createElement('ul');
ul.setAttribute("class", "domain_list");
newdiv.appendChild(ul);
for (j = 0; j < name.domains.length; ++j) {
ul.appendChild(make_li(name.domains[j], drag));
}
return newdiv;
}
The end result in the HTMl is basically:
<div class="container">
<ul class="parent0">
<li parentClass="parent0">
<li parentClass="parent0">
When recreating this structure, I need to have the class "parent0" and the parentClass attribute intact. Above you can see I've tried hiding the element, ensuring that it still stays a valid element with the correct classes/attributes, but in the end that still didn't work out. Ideally, I could remove the element entirely and recreate it with the correct classes.
If I am correct in my understanding of what you are trying to do, you do not need to .remove() and recreate the element in order to move it. You can just do this:
function copy_item(draggable, target) {
// not sure what this variable is for
// as you don't seem to be using it?
var account = clone_items(draggable);
// ...however, appending an existing
// element to another will 'move' it
// and preserve all of it's properties
target.append($('#' + name.uid));
}

JQuery replace html element contents if ID begins with prefix

I am looking to move or copy the contents of an HTML element. This has been asked before and I can get innerHTML() or Jquery's html() method to work, but I am trying to automate it.
If an element's ID begins with 'rep_', replace the contents of the element after the underscore.
So,
<div id="rep_target">
Hello World.
</div>
would replace:
<div id="target">
Hrm it doesn't seem to work..
</div>​
I've tried:
$(document).ready(function() {
$('[id^="rep_"]').html(function() {
$(this).replaceAll($(this).replace('rep_', ''));
});
});​
-and-
$(document).ready(function() {
$('[id^="rep_"]').each(function() {
$(this).replace('rep_', '').html($(this));
});
​});​
Neither seem to work, however, this does work, only manual:
var target = document.getElementById('rep_target').innerHTML;
document.getElementById('target').innerHTML = target;
Related, but this is only text.
JQuery replace all text for element containing string in id
You have two basic options for the first part: replace with an HTML string, or replace with actual elements.
Option #1: HTML
$('#target').html($('#rep_target').html());
Option #2: Elements
$('#target').empty().append($('#rep_target').children());
If you have no preference, the latter option is better, as the browser won't have to re-construct all the DOM bits (whenever the browser turns HTML in to elements, it takes work and thus affects performance; option #2 avoids that work by not making the browser create any new elements).
That should cover replacing the insides. You also want to change the ID of the element, and that has only one way (that I know)
var $this = $(this)
$this.attr($this.attr('id').replace('rep_', ''));
So, putting it all together, something like:
$('[id^="rep_"]').each(function() {
var $this = $(this)
// Get the ID without the "rep_" part
var nonRepId = $this.attr('id').replace('rep_', '');
// Clear the nonRep element, then add all of the rep element's children to it
$('#' + nonRepId).empty().append($this.children());
// Alternatively you could also do:
// $('#' + nonRepId).html($this.html());
// Change the ID
$this.attr(nonRepId);
// If you're done with with the repId element, you may want to delete it:
// $this.remove();
});
should do the trick. Hope that helps.
Get the id using the attr method, remove the prefix, create a selector from it, get the HTML code from the element, and return it from the function:
$('[id^="rep_"]').html(function() {
var id = $(this).attr('id');
id = id.replace('rep_', '');
var selector = '#' + id;
return $(selector).html();
});
Or simply:
$('[id^="rep_"]').html(function() {
return $('#' + $(this).attr('id').replace('rep_', '')).html();
});
From my question, my understanding is that you want to replace the id by removing the re-_ prefix and then change the content of that div. This script will do that.
$(document).ready(function() {
var items= $('[id^="rep_"]');
$.each(items,function(){
var item=$(this);
var currentid=item.attr("id");
var newId= currentid.substring(4,currentid.length);
item.attr("id",newId).html("This does not work");
alert("newid : "+newId);
});
});
Working Sample : http://jsfiddle.net/eh3RL/13/

jQuery add id to an element that is being appended to the body

I have the following function:
simpleModal: function (data, id) {
var responseHtml = data;
// Append the modal HTML to the DOM
var modalInstance = $('body').append(modalHtml);
$(modalInstance).attr('id', id);
$(id).find('.uiModalContent').width(480);
$(id).find('.uiModalContent').height(320);
// Hide the modal straight away, center it, and then fade it in
$(id).find('.uiModal').hide().center().fadeIn();
// Dynamically load in the passed data from the call
$(id).find('.uiModalContent').html($(responseHtml));
$(id).find('.uiModalContent').removeClass('loading');
$(id).find('.ModalClose').live('click', function (e) {
e.preventDefault();
$(this).parents('.uiModal').fadeOut(function () { $(this).parents('.uiModalWrapper').remove() });
});
},
when called like:
uiModal.simpleModal('<p>An error has occured</p>','TestError');
it should append the modal to the body with the passed content and give the modalHtml an id that is also passed. However it gets confused to appends the id to the body instead of the html. How do I get around this? Thanks
This is because the append method returns the element you are appending to, rather than the element you're appending.
Instead, you can use the appendTo method, and use it as follows;
var modalInstance = $(modalHtml).appendTo('body');
You also need to be using $('#' + id) as the ID selector as opposed to $(id); otherwise you'll end up looking for all elements with the tag name of TestError.
Additionally, you should seriously consider caching the result of $('#' + id); you're performing the same DOM lookup operation 6 times; which is totally unnecessary, as you have exactly the same jQuery object cached in var modalInstance; replace all instances of $('#' + id) to modalInstance
This point applies to $(id).find('.uiModalContent') as well; cache it!
var uiModelContent = modelInstance.find('.uiModalContent');
uiModelContent.height(320);
uiModelContent.width(480);
uiModelContent.html($(responseHtml));
uiModelContent.removeClass('loading');
Although you can also chain your methods for the same result;
modelInstance.find('.uiModalContent').height(320).width(480).html($(responseHtml)).removeClass('loading');

Categories

Resources