Create Element in Jquery - javascript

I would like to create element in Jquery/Javascript by using "div.someelement" like this
var SomeElement = $("div.someelement");
$( "#container" ).append( SomeElement );
But I don't want to copy element with the same class, I would like to create new one.
document.createElement is creating "<div.somelement>" instead of <div class="someelement">

I would use the following method to create elements on the fly
$("<div/>",{
"class" : "someelement",
// .. you can go on and add properties
"css" : {
"color" : "red"
},
"click" : function(){
alert("you just clicked me!!");
},
"data" : {
"foo" : "bar"
}
}).appendTo("#container");

Try this:
var $someelement = $('<div class="someelement"/>').appendTo('#container');
This will create a brand new element inside of #container and save it as $someelement for easy reference later.
http://api.jquery.com/jQuery/#jQuery2
UPDATE
You could clone the original then empty it out. This doesn't affect the original element at all.
var $someelement = $('div.someelement').clone().empty().appendTo('#container');

You can do this by the following:
var newElement = $('<div class="someelement"></div>');
$('#container').append(newElement);
or if you don't need the element you can directly append it:
$('#container').append('<div class="someelement"></div>');

According to the question you want to use a syntax like "div.someelement" to create an element.
In order to do that, you need to make your own parser.
It is very simple if that will be the exact syntax.
var str = "div.someelement",
parts = str.split("."),
elem = $("<" + parts.shift() + ">"),
cls;
while (cls = parts.shift())
elem.addClass(cls);
But if you're going to do this, you might as well use native methods.
var str = "div.someelement",
parts = str.split("."),
elem = document.createElement(parts.shift());
elem.className = parts.join(" ");
If you want to allow for full CSS syntax for creating an element, then you may want to look at the regex parser that Sizzle uses, and use it for your needs.

Use this:
var someElement = $("<div></div>");
someElement.addClass("someelement");
$("#container").append(someElement);
Or you can chain together the calls:
$("#container").append(
$("<div></div>")
.addClass("someelement")
);
EDIT:
Perhaps I misunderstood the question, maybe this will help. To create a new set of elements, use jQuery's clone method:
$("div.someelement").clone().appendTo("#container");

I would use zen coding for textarea as a starting point. Its syntax is close enough for what you are trying to do, its a well understood implementation. You should be able to invoke the transformation from a raw string rather than from a textarea with a little tweaking.

Since you are asking about creating an element from css syntax, you need to use a parser to interpret the syntax.
Here is an example you can build from. This will match an element name followed by id, class or other attributes. It won't cover some edge cases, but will work in most cases.
var elem_regex = /^(\w+)?|(#|\.)([^.#\[]+)|(\[[^\]]+?\])/g
Then make a function to get the parts and create an element.
function elementFromSelector(str) {
var match, parts = {}, quote_re = /^("|').+(\1)$/;
while (match = elem_regex.exec(str)) {
if (match[1])
parts.name = match[1];
else if (match[2] === ".") {
if (!parts.clss)
parts.clss = [];
parts.clss.push(match[3]);
} else if (match[2] === "#")
parts.id = match[3];
else if (match[4]) {
var attr_parts = match[4].slice(1,-1).split("="),
val = attr_parts.slice(1).join("");
parts[attr_parts[0]] = quote_re.test(val) ? val.slice(1,-1) : val;
}
else throw "Unknown match";
}
if (parts.name) {
var elem = document.createElement(parts.name);
delete parts.name;
for (var p in parts)
if (p === "clss")
elem.className = parts[p].join(" ");
else
elem[p] = parts[p];
return elem;
} else throw "No element name at beginning of string";
}
Then pass a proper string to the function, and it will return the element.
var str = 'input#the_id.firstClass.secondClass[type="text"][value="aValue"]';
var element = elementFromSelector(str);
Before creating the element, the parts look like this.
{
"name": "input",
"id": "the_id",
"clss": [
"firstClass",
"secondClass"
],
"type": "text",
"value": "aValue"
}
Then it uses that info to create the element that gets returned.

Simply create a new Element for jQuery:
var $newElement = $(document.createElement("div"));
$newElement.appendTo($("body"));
if you want to at attributes to de element simplie use:
$newElement.attr({
id : "someId",
"class" : "someClass"
});
Rember by class always use like this "class", because class is a reserved name

Related

if statement inside jQuery selector

I'm getting those 2 vars from the DOM:
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
and I want here to find the classes in my DOM and show it
$('.filter-result').find('.'+get_category, '.'+get_subcategory ).show();
But I need to write it inside the .find() only if the variables are exist
I hope it answers your question:
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
var classes = [];
if (get_category) {
classes.push('.' + get_category);
}
if (get_subcategory) {
classes.push('.' + get_subcategory);
}
//if get_category or get_subcategory were found
if (classes.length) {
$('.filter-result').find(classes.join('')).show();
}
I do like Gabriels answer because it is very simple another option that works well and is extensible all you would have to do add another selector is add it to the selectors array. It is a little bit more advanced using javascripts filter and map array methods though.
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
var selectors = [get_category, get_subcategory];
var query = selectors.filter(function(elem) {
if (elem) { return elem };
}).map(function(elem){
return '.' + elem;
}).join(', ')
$('.filter-result').find(query).show();

jQuery append element if it doesn't exist, otherwise replace

Here's a short piece of code:
var $el = $("#something").find(".test");
if (!$el.length) {
$("#something").append('<div class="test">somecontent</div>');
} else {
$el.replaceWith('<div class="test">somenewcontent</div>');
}
I couldn't find a method appendOrReplaceWith or anything similar.
Any ideas how can I make it shorter?
I believe that:
$("#something").appendOrReplace('<div class="test">sometext</div>');
would be much easier to read, but no such method is available yet.
Just remove it first then append.
$(".test").remove();
$("#something").append('<div class="test">somecontent</div>');
Mandatory vanilla answer. It may not be shorter, but it's faster.
Get the element, grab all subelements with the class "test", create your div, check the subelements length, and if length is truthy, set the innerHTML to the div. Else, append it.
var el = document.getElementById("something");
var subel = el.getElementsByClassName("test");
var div = document.createElement("div");
div.className = "test"
if (subel.length) {
div.textContent = "somenewcontent";
while(el.hasChildNodes()) el.removeChild(el.lastChild); //remove child nodes
el.appendChild(div);
} else {
div.textContent = "somecontent";
el.appendChild(div);
}
Adding a method like findOrAppend to jQuery could be useful:
$.fn.findOrAppend = function(selector, content) {
var elements = this.find(selector);
return elements.length ? elements : $(content).appendTo(this);
}
Then you can chain text, replaceWith, empty etc. as needed:
$("#something")
.findOrAppend(".test", "<div class='test'>")
.text("newcontent");
First of all you should cache your selectors:
var $som = $('#something');
var $ele = $(".test",$som);
var newHtml = '<div class="test">somecontent</div>';
if (!$el[0]) $som.append( newHtml );
else $ele.replaceWith( newHtml );
but you already did it really fine, (beside not caching repeated selectors), and me, trying to make it smaller could be a**-kicked for not using {} for my if and else :)
I would do this
var $s = $("#something"), $t = $s.find(".test"), c = 'New content';
( $t[0] ? $t:$s)[( $t[0] ? 'html':'append')](( $t[0] ? c :$('<div>',{class:'test'}).append(c)));

Getting Attributes from User submitted text! RegExp?

I am trying to pull the attributes out of piece of submitted text in Javascript and change it to an array.
So the user submits this:
<iframe src="http://www.stackoverflow.com/" width="123" height="123" frameborder="1"></iframe>
and I would get:
arr['src'] = http://www.stackoverflow.com/
arr['width'] = 123
arr['height'] = 123
arr['frameborder'] = 1
Just need a regexp I think but any help would be great!
I recommend to use a RegExp to parse user-inputed HTML, instead of creating a DOM object, because it's not desired to load external content (iframe, script, link, style, object, ...) when performing a "simple" task such as getting attribute values of a HTML string.
Using similar (although similarcontradiction?) methods as in my previous answer, I've created a function to match quoted attribute values. Both quoted, as non-quoted attributes are matched.
The code currently returns an object with attributes from the first tag, but it's easily extensible to retrieve all HTML elements (see bottom of answer).
Fiddle: http://jsfiddle.net/BP4nF/1/
// Example:
var htmlString = '<iframe src="http://www.stackoverflow.com/" width="123" height="123" frameborder="1" non-quoted=test></iframe>';
var arr = parseHTMLTag(htmlString);
//arr is the desired object. An easy method to verify:
alert(JSON.stringify(arr));
function parseHTMLTag(htmlString){
var tagPattern = /<[a-z]\S*(?:[^<>"']*(?:"[^"]*"|'[^']*'))*?[^<>]*(?:>|(?=<))/i;
var attPattern = /([-a-z0-9:._]+)\s*=(?:\s*(["'])((?:[^"']+|(?!\2).)*)\2|([^><\s]+))/ig;
// 1 = attribute, 2 = quote, 3 = value, 4=non-quoted value (either 3 or 4)
var tag = htmlString.match(tagPattern);
var attributes = {};
if(tag){ //If there's a tag match
tag = tag[0]; //Match the whole tag
var match;
while((match = attPattern.exec(tag)) !== null){
//match[1] = attribute, match[3] = value, match[4] = non-quoted value
attributes[match[1]] = match[3] || match[4];
}
}
return attributes;
}
The output of the example is equivalent to:
var arr = {
"src": "http://www.stackoverflow.com/",
"width": "123",
"height": "123",
"frameborder": "1",
"non-quoted": "test"
};
Extra: Modifying the function to get multiple matches (only showing code to update)
function parseHTMLTags(htmlString){
var tagPattern = /<([a-z]\S*)(?:[^<>"']*(?:"[^"]*"|'[^']*'))*?[^<>]*(?:>|(?=<))/ig;
// 1 = tag name
var attPattern = /([-a-z0-9:._]+)\s*=(?:\s*(["'])((?:[^"']+|(?!\2).)*)\2|([^><\s]+))/ig;
// 1 = attribute, 2 = quote, 3 = value, 4=non-quoted value (either 3 or 4)
var htmlObject = [];
var tag, match, attributes;
while(tag = tagPattern.exec(htmlString)){
attributes = {};
while(match = attPattern.exec(tag)){
attributes[match[1]] = match[3] || match[4];
}
htmlObject.push({
tagName: tag[1],
attributes: attributes
});
}
return htmlObject; //Array of all HTML elements
}
Assuming you're doing this client side, you're better off not using RegExp, but using the DOM:
var tmp = document.createElement("div");
tmp.innerHTML = userStr;
tmp = tmp.firstChild;
console.log(tmp.src);
console.log(tmp.width);
console.log(tmp.height);
console.log(tmp.frameBorder);
Just make sure you don't add the created element to the document without sanitizing it first. You might also need to loop over the created nodes until you get to an element node.
Assuming they will always enter an HTML element you could parse it and read the elements from the DOM, like so (untested):
var getAttributes = function(str) {
var a={}, div=document.createElement("div");
div.innerHTML = str;
var attrs=div.firstChild.attributes, len=attrs.length, i;
for (i=0; i<len; i++) {
a[attrs[i].nodeName] = attrs[i].nodeValue];
}
return a;
};
var x = getAttributes(inputStr);
x; // => {width:'123', height:123, src:'http://...', ...}
Instead of regexp, use pure JavaScript:
Grab iframe element:
var iframe = document.getElementsByTagName('iframe')[0];
and then access its properties using:
var arr = {
src : iframe.src,
width : iframe.width,
height : iframe.height,
frameborder : iframe.frameborder
};
I would personally do this with jQuery, if possible. With it, you can create a DOM element without actually injecting it into your page and creating a potential security hazard.
var userTxt = '<iframe src="http://www.stackoverflow.com/" width="123" height="123" frameborder="1"></iframe>';
var userInput = $(userTxt);
console.log(userInput.attr('src'));
console.log(userInput.attr('width'));
console.log(userInput.attr('height'));
console.log(userInput.attr('frameborder'));

Get link name in javascript

Example
Example Name
I would like to get "Example Name"
I know I can do this with regex, but I'm looking for a simpler, faster approach. The closest I came was with Jquery using the .attr("href") attribute. I tried putting .attr("title"), but that doesn't work since I technically don't have a title there.
.text()
Try this
var t = $('a').text();
alert(t);
http://jsfiddle.net/jasongennaro/gZsbW/
Of course, this targets the first link it encounters. Better if you can hook it to an ID.
Example
Example Name
Then
var t = $('#linkName').text();
You can use something like this, which works in regular Javascript...
This has the advantage that it will extract the text from things like:
This is a <i>link</i> with <b>markup</b>
var getText = function(el) {
var ret;
var txt = [],i=0;
if (!el) {
ret = "";
} else if (el.nodeType === 3) {
// No problem if it's a text node
ret = el.nodeValue;
} else {
// If there is more to it, then let's gather it all.
while(el.childNodes[i]) {
txt[txt.length] = self.getText(el.childNodes[i]);
i++;
}
// return the array as a string
ret = txt.join("");
}
return ret;
};
Try var LinkName = document.links.text;
Or for IE you will need var LinkName = document.links.innerText

What's the effectiviest way of creating an element with multiple attributes and appending it to another element and have it available as a variable??

I wonder what's the effectiviest way of creating an element with id='id' class='class' attr='attr' .. and appending it to another element and have it available as a variable?
So far I can do it with one line of code. But it requires a new set of javascript framework. I just want to make sure that there is no effectivier way first.
My solution is to create a javascript framework, which got the following syntax:
var variable = elementTagAppend/Prepend/After/Before('JQuerySelector', elementToAppend/Prepend/After/BeforeTo);
For instance, if I want to create an div element with id='id', class='class', attr='attr' and append it to an another element called "another"
var variable = divAppend('#id.class[attr = "attr"]', another); Very effective right?
Or if I want to prepend a form element with id='inputForm', class='inputForms':
var variable = formPrepend('#inputForm.inputForms', another);
var element = $("<div/>", {
id: "id",
class: "class",
attr: "attr"
}).appendTo("#element");
appendTo returns a JQuery object, you can read more on http://api.jquery.com/appendTo/
Edit: It looks like you're asking if an effective way to create elements is having methods for all HTML tags, so that your library doesn't have to do any sort of text parsing/regex.
This isn't a solution as it makes development a lot slower.
One way is to use a function and DOM methods:
<script type="text/javascript">
var elementData = {
tagName: 'div',
properties: {
id: 'div0',
onclick: function(){alert(this.id);},
className: 'someClass'
},
content: '<h1>New Div</h1>'
}
function elementBuilder(obj) {
var el = document.createElement(obj.tagName);
var props = obj.properties;
for (var p in props) {
if (props.hasOwnProperty(p)) {
el[p] = props[p];
}
}
if (typeof obj.content == 'string') {
el.innerHTML = obj.content;
}
return el;
}
</script>
<button onclick="
var newElement = elementBuilder(elementData);
document.body.insertBefore(newElement, this.nextSibling);
">Insert element</button>
The above could be expanded to create more than one element per call, I'll leave that you.
Another method is to take an HTML string, convert it to an element (or elements) and return it in a document fragment:
<script type="text/javascript">
var htmlString = '<p><b>paragraph</b></p>' +
'<p>Another p</p>';
function byInnerHTML(s) {
var d = document.createElement('div');
d.innerHTML = s;
var frag = document.createDocumentFragment();
while (d.firstChild) {
frag.appendChild(d.firstChild);
}
return frag;
}
</script>
<button onclick="
var newContent = byInnerHTML(htmlString);
document.body.insertBefore(newContent, this.nextSibling);
">Insert element</button>
The second one returns a document fragment that can be inserted into the page. Of course if you want to generate parts of a table, the second method isn't quite so good.
In tune with a pure JavaScript implementation, here's my take on the problem:
function createElement(type, attributes, parent){
var node = document.createElement(type);
for (i in attributes){
node.setAttribute(i, attributes[i])
}
if (parent && parent.__proto__.appendChild){
parent.appendChild(node)
}
return node;
}
And you use it like this:
createElement("span", { "id": "theID", "class": "theClass", "title": "theAttribute"}, document.getElementById("theParent"))
I kept one of your initial requirements: append the node to some other element and also return it.
I particularly like RobG's second example with the fragment. Definitely something I'd try if I were using plain strings to represent HTML.
If it doesn't warrant the use-case, it doesn't always make sense to import a JS framework. jQuery is no exception. Should you decide more complex workflows are needed, that's your warrant! ;)

Categories

Resources