My jQuery wrap method doesn't work - javascript

I'm trying to use jQuery wrap but it doesn't work.
(function ($) {
$.fn.taggify = function () {
create(this);
return this;
};
function create($theElement) {
var $input = $('<input></input>')
.attr('type', 'text')
.attr('autocomplete', 'off')
.css('border', 'none')
.css('outline', 'none')
.wrap('<li></li>');
$input.on('keyup', function (e) {
if (e.keyCode === 13) {
var tagText = $input.val();
var $span = $('<span class="tag-label"></span>');
$span.text(tagText).wrap('<li class="tag-choice"></li>');
$theElement.prepend($span);
}
});
$theElement.append($input);
}
})(jQuery);
The result still doesn't have <li> tag wrapped around the input
Here's the jsfiddle
http://jsfiddle.net/noppanit/sryg5fk7/1/

just move your wrap code after append input element .
DEMO
$theElement.append($input);
$input.wrap('<li />');
$theElement.prepend($span);
$span.text(tagText).wrap('<li class="tag-choice"></li>');

You can wrap it using:
(function ($) {
$.fn.taggify = function () {
var $input = $('<input />')
.addClass('specialInput')
.attr('type', 'text')
.attr('autocomplete', 'off')
.css('border', 'none')
.css('outline', 'none')
.wrap('<li />');
$(this).append($input);
return this;
};
})(jQuery);
$('body').on('keyup','.specialInput',function (e) {
if (e.keyCode === 13) {
$('<li class="tag-choice"><span class="tag-label">'+$(this).val()+'</span></li>').prependTo($(this).parent());
}
});
Looking at the console, the error surrounds trying to use the .on() command on a non DOM element

Not quite sure why, but look like you wanna wrap the element that not exist yet. Unless wrap the element after prepend should work like so :
$theElement.append($input);
$input.wrap('<li></li>');
$theElement.prepend($span);
$span.text(tagText).wrap('<li class="tag-choice"></li>');
See DEMO
p/s : This only an alternative solution for your problem, not sure why the original code did't worked either.

How about using like this?
var $input = $('<li><input></input></li>')//wrap li here
.find('input')//find input and use as you want
.attr('type', 'text')
.attr('autocomplete', 'off')
.css('border', 'none')
.css('outline', 'none');
I also noticed that you're using on method but this wouldn't work as the element is dynamically created. So replace this line:
$input.on('keyup', function (e) {
With this:
$(document).on('keyup', $input, function (e) {
//you may use closest parent element instead of document
your updated fiddle

Related

How to pass "this" on an enter key event?

I think this is a syntax question, but I can't seem to find a question that answers what I'm looking for. There's lots that are... close. Might be something with binding, or "apply", but I can't figure out how to use those in this context.
I have a function, that when fired, turns a span into an input so it can be edited. Then, when the focus is off (blur), the new text is saved. So far that works exactly as I wanted. I thought it would be nice if enter key would do the same thing... but I can't figure out how to make the event work.
function span_into_textarea() {
var old_text = $(this).text();
var editableText = $("<input type='text' />");
editableText.val(old_text);
$(this).replaceWith(editableText);
editableText.focus();
editableText.blur(textarea_into_span);
editableText.keypress(function (e) {
if (e.which == 13) {textarea_into_span()}
}); // THIS DOESNT PASS ANYTHING TO "THIS"
editableText.keypress(textarea_into_span); //THIS WORKS BUT I CAN'T KNOW WHICH KEY WAS PRESSED
}
function textarea_into_span() {
var new_text = $(this).val();
}
Thanks for any help!
You can use call to pass the this reference:
editableText.keypress(function (e) {
if (e.which == 13) {textarea_into_span.call(this)} //will refer to editableText
});
You may bind: editableText.keypress( textarea_into_span.bind(this) ) (event is passed as an argument).
You may replace textarea_into_span with an arrow function (they don't bind this so it is looked up in parent context):
editableText.keypress( (e) => {
if (e.which == 13) {
var new_text = $(this).val();
}
})
As suggested by #Mouser you may use call or apply:
editableText.keypress( function(e) {
if (e.which == 13) {
textarea_into_span.call(this);
// or textarea_into_span.apply(this)
}
})
Try this way, you were losing the scope:
function span_into_textarea() {
var modify = this;
var old_text = $(this).text();
var editableText = $("<input type='text' />");
editableText.val(old_text);
$(this).replaceWith(editableText);
editableText.focus();
editableText.blur(textarea_into_span(modify));
editableText.keypress(function (e) {
if (e.which == 13) {textarea_into_span(modify)}
});
}
function textarea_into_span(modify) {
var new_text = $(modify).val();
}
editableText.keypress(function(e) {
var key = e.which;
if (key == 13) // enter key ascii code
{
textarea_into_span.call(this) //will refer to editableText
}
});

jquery rename content insite a tag and confirming it

How can I target only one container?
The User should be able to change the Name and then confirm the change.
My function works fine but when I have more containers repeated and I confirm Its changing all the tags!
Please check the demo where you can also see the changeElementTypefunction
Demo:
http://jsfiddle.net/26qNq/1/
JS:
$('.replace').on('click', function (){
$("h2").changeElementType("textarea");
$(this).hide();
$(this).next('a').show();
$('.confirm').on('click', function(){
var $textarea = $('textarea');
$(this).hide();
$(this).prev('a').show();
$textarea.html($textarea.val()).changeElementType("h2");
});
if ($('textarea:visible')){
$(document).keypress(function(e) {
if(e.which == 13) {
alert('You pressed enter!');
$("textarea").changeElementType("h2");
$('.replace').css('opacity','1');
}
});
}
});
You need to identify the relevant h2/textarea
var container = $(this).closest('.rename')
container.find('h2').changeElementType("textarea");
and
var container = $(this).closest('.rename')
var $textarea = container.find('textarea');
You also should nest your handler binding because each time your try to edit, you add a new handler
Full changes
$(document).keypress(function (e) {
if ($('textarea:visible')) {
if (e.which == 13) {
alert('You pressed enter!');
$("textarea").changeElementType("h2");
$('.replace').css('opacity', '1');
}
}
});
$('.replace').on('click', function () {
var container = $(this).closest('.rename')
container.find('h2').changeElementType("textarea");
$(this).hide();
$(this).next('a').show();
});
$('.confirm').on('click', function () {
var container = $(this).closest('.rename')
var $textarea = container.find('textarea');
$(this).hide();
$(this).prev('a').show();
$textarea.html($textarea.val()).changeElementType("h2");
});
Demo at http://jsfiddle.net/26qNq/6/
Adding an ID to each of them seems to work.
All I needed to do was add a numeric ID to each element we were using and add this to your replace code:
var id = $(this).attr('id');
$("h2#" + id).changeElementType("textarea");
demo: http://jsfiddle.net/26qNq/12/

How to match children innerText with user input using jQuery

I have the following structure:
<div id="campaignTags">
<div class="tags">Tag 1</div>
<div class="tags">Tag 2</div>
<div class="tags">Tag 3</div>
</div>
And I'm trying to match user input against the innerText of each children of #campaignTags
This is my latest attempt to match the nodes with user input jQuery code:
var value = "Tag 1";
$('#campaignTags').children().each(function(){
var $this = $(this);
if(value == $(this).context.innerText){
return;
}
The variable value is for demonstration purposes only.
A little bit more of context:
Each div.tags is added dynamically to div#campaignTags but I want to avoid duplicate values. In other words, if a user attempts to insert "Tag 1" once again, the function will exit.
Any help pointing to the right direction will be greatly appreciated!
EDIT
Here's a fiddle that I just created:
http://jsfiddle.net/TBzKf/2/
The lines related to this question are 153 - 155
I tried all the solutions, but the tag is still inserted, I guess it is because the return statement is just returning the latest function and the wrapper function.
Is there any way to work around this?
How about this:
var $taggedChild = $('#campaignTags').children().filter(function() {
return $(this).text() === value;
});
Here's a little demo, illustrating this approach in action:
But perhaps I'd use here an alternative approach, storing the tags within JS itself, and updating this hash when necessary. Something like this:
var $container = $('#campaignTags'),
$template = $('<div class="tags">'),
tagsUsed = {};
$.each($container.children(), function(_, el) {
tagsUsed[el.innerText || el.textContent] = true;
});
$('#tag').keyup(function(e) {
if (e.which === 13) {
var tag = $.trim(this.value);
if (! tagsUsed[tag]) {
$template.clone().text(tag).appendTo($container);
tagsUsed[tag] = true;
}
}
});
I used $.trim here for preprocessing the value, to prevent adding such tags as 'Tag 3 ', ' Tag 3' etc. With direct comparison ( === ) they would pass.
Demo.
I'd suggest:
$('#addTag').keyup(function (e) {
if (e.which === 13) {
var v = this.value,
exists = $('#campaignTags').children().filter(function () {
return $(this).text() === v;
}).length;
if (!exists) {
$('<div />', {
'class': 'tags',
'text': v
}).appendTo('#campaignTags');
}
}
});
JS Fiddle demo.
This is based on a number of assumptions, obviously:
You want to add unique new tags,
You want the user to enter the new tag in an input, and add on pressing enter
References:
appendTo().
filter().
keyup().
var value = "Tag 1";
$('#campaignTags').find('div.tags').each(function(){
if(value == $(this).text()){
alert('Please type something else');
}
});
you can user either .innerHTML or .text()
if(value === this.innerHTML){ // Pure JS
return;
}
OR
if(value === $this.text()){ // jQuery
return;
}
Not sure if it was a typo, but you were missing a close } and ). Use the jquery .text() method instead of innerText perhaps?
var value = "Tag 1";
$('#campaignTags').find(".tags").each(function(){
var content = $(this).text();
if(value === content){
return;
}
})
Here you go try this: Demo http://jsfiddle.net/3haLP/
Since most of the post above comes out with something here is another take on the solution :)
Also from my old answer: jquery - get text for element without children text
Hope it fits the need ':)' and add that justext function in your main customised Jquery lib
Code
jQuery.fn.justtext = function () {
return $(this).clone()
.children()
.remove()
.end()
.text();
};
$(document).ready(function () {
var value = "Tag 1";
$('#campaignTags').children().each(function () {
var $this = $(this);
if (value == $(this).justtext()) {
alert('Yep yo, return');)
return;
}
});
//
});

how to pass $(this) object from one function to another?

I think its very basic Object oriented javaScript related question. But I'm still very confused about it. I would like to pass $(this) object from 1 function to another. So that I can get the href attr of the link clicked.
Here my sample code
HTML
TEST
TEST
JS
$(document).on("click", ".test", function () {
var $this = $(this);
var rel = $this.attr("rel");
if (rel == "image") {
e.preventDefault();
openImage($this);
} else if (rel == "video") {
openVideo($this);
}
});
function openImage($this) {
var href = $this.attr("href");
alert(href);
}
Check out the examples in the jQuery documentation page. You'll find that the on method applies to the selected elements, in the case of your code, it's the document object. To get the attribute that you want, jQuery is not necessary to wrap the element. Here's a JSBin example. One more thing, try reemplace == with === to get type checking also. Hope it helps
My question had 1 small syntax error please (check 1st comment on question)
Following is the code I ended up using.
$(document).on("click", ".test", function (e) {
var anchor = $(this);
var rel = anchor.attr("rel");
if (rel == "image") {
e.preventDefault();
openImage(anchor);
} else if (rel == "video") {
openVideo(anchor);
}
});
function openImage(anchor) {
var href = anchor.attr("href");
alert(href);
}
Thank you!

Why is my jquery .each() function not working properly?

I wrote this function:
jQuery(document).ready(function() {
jQuery('input[type=text]').each( function(i) {
thisval = jQuery(this).val();
jQuery(this).blur( function() {
if (jQuery(this).val() == '') {
jQuery(this).val(thisval);
}
}); // end blur function
jQuery(this).focus( function() {
if (jQuery(this).val() == thisval) {
jQuery(this).val('');
};
});// end focus function
}); //END each function
}); // END document ready function
It's designed to get the value of an input, then if the user clicks away without entering a new value, the old value returns. This works properly with one of the inputs on the page, but not the others. However, when I remove the .blur and .focus functions and just use alert(thisval); it alerts the name of each input, so something is wrong with my function, but I can't figure out what. Any help?
You need var when declaring your variable so it's not a global one being shared, like this:
var thisval = jQuery(this).val();
Also since you're dealing specifically with text inputs you can just use the .value DOM property, like this:
jQuery(function() {
jQuery('input[type=text]').each(function(i) {
var thisval = this.value;
jQuery(this).blur( function() {
if (this.value == '') this.value = thisval;
}).focus( function() {
if (this.value == thisval) this.value = '';
});
});
});
thisval is a global variable so it is replaced with each loop. Make it local [stick var in front of it] and it should work like magic.
You should not just keep creating jQuery(this) over and over again. That is very inefficient. jQuery(this) is expensive. You should store one copy in a variable and use the variable.

Categories