-1

According to the jQuery API's Documentation I'm using the correct event handler.

I'm also aware of the IE issue stated as well, and I don't care, as this is merely just a playful experiment.

Note: Attempting to change the type property (or attribute) of an input element created via HTML or already in an HTML document will result in an error being thrown by Internet Explorer 6, 7, or 8.

So I have been trying to get this to work and I'm left with a few questions:

  1. Is this possible?
  2. If so what am I doing wrong & how can I fix it?

Edit

My intention is to change .selected's tag from a span to whatever the user specified. I originally used a button as an example, but I saw how easily my post was misunderstood. As my intentions are to change the span tag to anything from a button to a input[type=text] element. All depending on what the user types in a textbox.

I don't see how replaceWidth is going to help me in this case. How can I understand more about this?

$(document).ready(function() {
  // Show active tag
  $(".activetag").html( $(".selected").prop("tagName").toLowerCase() );

  // Change selected element's tag
  $(".convert").on("keyup", function() {
    $(".selected").replaceWidth( $("div") ).html( $(".selected").html() );
  });

  // Show selected element's code
  // ex. <span class="selected">Hello world</span>
  $(".code").val( $(".selected").html() );
});
<!DOCTYPE html>
<html>
  <head>
    <title>new document</title>
    <meta charset='utf-8'>
    <meta name='viewport' content='initial-scale=1.0'>
    <meta http-equiv='X-UA-Compatible' content='IE=9' />
    <link type='text/css' rel='stylesheet' href='http://necolas.github.io/normalize.css/3.0.1/normalize.css'/>
    <script type='text/javascript' src='http://code.jquery.com/jquery-latest.min.js'></script>
  </head>
  <body>
    <div align="center">
      <span class="activetag">Hello world</span><br />
      <input type="text" class="convert"><br />
      <span class="selected">Hello world</span><br />
      <textarea class="code"></textarea>
    </div>
  </body>
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186
Michael Schwartz
  • 8,153
  • 14
  • 81
  • 144
  • 3
    What makes you think you can change the `.tagName`? The usual solution is to replace the current tag (and its children) with new DOM elements of the type you want. – jfriend00 Jan 01 '15 at 22:06
  • And, some other replacement solutions: http://stackoverflow.com/questions/2815683/jquery-javascript-replace-tag-type and http://upshots.org/javascript/jquery-change-tag-name – jfriend00 Jan 01 '15 at 22:10
  • It's not a dupe imo as it seems the op is confusing an input type attribute with a tagname and probably needs `$(".selected").attr("type", "button");` – andrew Jan 01 '15 at 22:10
  • @andrew - the OP's title and question both refer to changing `.tagName`. They may be confused, hard to tell. If the OP cares to clarify, then we can adapt to that. – jfriend00 Jan 01 '15 at 22:13
  • @jfriend00 mistakenly, I believe, note the jQuery docs that were attached. The incorrect terminology was used when asking the question – andrew Jan 01 '15 at 22:17
  • 1
    @andrew - so, it's up to the OP to clarify their question then, not us to guess what they "might" have actually meant. – jfriend00 Jan 01 '15 at 22:18
  • @jfriend00 fair point – andrew Jan 01 '15 at 22:19
  • 2
    The [*tagName*](http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-104682815) property is readonly, you can't change it. You can, as jfriend00 suggests, replace one element with another with attributes and properties copied from one to another. But not all properties are common between elements, e.g. a checkbox has a checked attribute, a text input doesn't. – RobG Jan 01 '15 at 22:28
  • JQuery docs clearly states that `tagName [...] should be retrieved and set with the .prop() method.` – Robert Jan 02 '15 at 03:30
  • @Robert—the jQuery documentation is clearly wrong about that. It's helpful to include a link to the relevant page when quoting (e.g. [*jQuery prop()*](http://api.jquery.com/prop/)). ;-) – RobG Jan 02 '15 at 12:03

3 Answers3

0

JS to change the tag name

/**
 * This function replaces the DOM elements's tag name with you desire
 * Example:
 *        replaceElem('header','ram');
 *        replaceElem('div.header-one','ram');
 */
function replaceElem(targetId, replaceWith){
  $(targetId).each(function(){
    var attributes = concatHashToString(this.attributes);
    var replacingStartTag = '<' + replaceWith + attributes +'>';
    var replacingEndTag = '</' + replaceWith + '>';
    $(this).replaceWith(replacingStartTag + $(this).html() + replacingEndTag);
  });
}
replaceElem('div','span');

/**
 * This function concats the attributes of old elements
 */
function concatHashToString(hash){
  var emptyStr = '';
  $.each(hash, function(index){
    emptyStr += ' ' + hash[index].name + '="' + hash[index].value + '"';
  });
  return emptyStr;
}

Related fiddle is in this link

Shiva
  • 11,485
  • 2
  • 67
  • 84
  • can see this link also https://cbabhusal.wordpress.com/2015/01/04/dynamically-change-html-tag-of-elements/ – Shiva Jan 04 '15 at 13:06
0

Here's a little ditty that does the job:

var el = document.querySelector('.js-the-thing');
var outer = el.outerHTML;
el.parentElement.innerHTML = outer.replace(/(<)(\/)?strong\b/gi, '$1$2em');

Example: replace strong with em

var outer = "<strong><stronger><strong yes></strong></stronger></strong>";
outer.replace(/(<)(\/)?strong\b/gi, '$1$2em');

"<em><stronger><em yes></em></stronger></em>"

Bear in mind that you lose any event handlers that where attached to the element, but if you're using the standard practice of attaching listeners up at the component level, or the barbaric practice of onclick=, you'll be fine.

If you don't want to replace all of the similarly tagged elements you could also use .innerHTML to save them and then replace the .innerHTML of the new element.

coolaj86
  • 74,004
  • 20
  • 105
  • 125
-1

So after learning that you can't change the tagName directly itself. There's still a few ways to do this.

The sample below is by using a hidden textarea to hold are html and changing our tag using a textbox, a button, and .replaceWith. This way we have more control rather than just using keyup. Also this way I don't have to worry about loosing my element, but also I'm saving processing power as I don't have the browser doing anymore work than it needs to do.

Here's a fiddle using a JQuery plugin called .replaceTagName. (This plugin was not not handy for my needs. As I also wanted to call input[type=text] and this plugin would not allow such a thing as it handles html not values. However this plugin may still be helpful for someone else)

Here's a demo of the same thing below, but instead I'm using conditional/ternary operators instead.

$(document).ready(function() {

  // Change selected element's tag function
  var changeTagName = function() {
    var $val = $(".newtag").val().trim().toLowerCase();

    // If no value is set return to default
    if ($.inArray($val, [""]) > -1) {
      $(".selected").replaceWith( "<span class=\"selected\" \>");
      $(".selected").html( $(".code").val() );
      // Check if it's a textbox
    } else if ($.inArray($val, ["input[type=text]", "input", "textbox"]) > -1) {
      $(".selected").replaceWith( "<input type=\"text\" class=\"selected\" \>");
      $(".selected").val( $(".code").val() );

      // Check if it's an input button
    } else if ( $val === "input[type=button]" ) {
      $(".selected").replaceWith( "<input type=\"button\" class=\"selected\" \>");
      $(".selected").val( $(".code").val() );

      // Check if it's a textarea
    } else if ( $val === "textarea" ) {
      $(".selected").replaceWith( "<" + $val + " class=\"selected\" \>");
      $(".selected").val( $(".code").val() );

      // Use text as a placeholder to make a span tag
    } else if ( $val === "text" ) {
      $(".selected").replaceWith( "<span class=\"selected\" \>");
      $(".selected").html( $(".code").val() );
    } else {

      // Make any others specified
      $(".selected").replaceWith( "<" + $val + " class=\"selected\" \>");
      $(".selected").html( $(".code").val() );
    }

    // Return tagName
    $(".newtag").val( $(".selected").prop("tagName").toLowerCase() );
  };

  // Change tagName from "Enter" Key
  $(document).keydown(function(e) {
    if ($(".newtag").is(":focus")) {
      if (e.which === 13) {
        changeTagName();
      }
    }
  });

  // Change selected element's tag
  $(".convert").on("click", function() {
    changeTagName();
  });

  // Show selected element's code
  // ex. <span class="selected">Hello world</span>
  $(".code").val( $(".selected").html() );
});
.hide {
  display: none;
}
<!DOCTYPE html>
<html>
  <head>
    <title>new document</title>
    <meta charset='utf-8'>
    <meta name='viewport' content='initial-scale=1.0'>
    <meta http-equiv='X-UA-Compatible' content='IE=9' />
    <link type='text/css' rel='stylesheet' href='http://necolas.github.io/normalize.css/3.0.1/normalize.css'/>
    <script type='text/javascript' src='http://code.jquery.com/jquery-latest.min.js'></script>
  </head>
  <body>
    <div align="center">
      <input type="text" class="newtag" placeholder="tagName here..."><br />
      <input type="button" class="convert" value="convert"><br />
      <span class="selected">Hello world</span><br />
      <textarea class="code hide"></textarea>
    </div>
  </body>
</html>
Michael Schwartz
  • 8,153
  • 14
  • 81
  • 144