Calling a JavaScript function inside a jQuery generated <a href...> - javascript

I have a problem with this piece of code:
$(document).ready(function() {
$('.notActiveId').change(function() {
if ($(this).attr('value').length === 0 ) {
$("#notActiveButton").html('');
} else {
$("#notActiveButton").html('<a href="javascript:void(0)" onClick="setStatus(' + $(this).attr('value') + ', activate)" class="operationUnlock" >Activate</a>');
}
});
});
I'm calling with $(this).attr('value') a value from a select list named notActiveId. But the problem is how to write $(this).attr('value') in setStatus() function, because value of my select is in this form: RZT_83848Rer (so it consists of characters, underline and numbers).
If I try to write it as above, then I get a JavaScript error.

Instead of using an old-school "onclick", why not add your element via jQuery?
$('#notActiveButton').empty().append($('<a/>', {
href: '#', // the "javascript:" thing is basically bogus and unnecessary
click: function () {
setStatus(this.value, activate);
},
class: 'operationUnlock',
text: 'Activate'
}));
Now, all this assumes that your "notActiveButton" element is some sort of legitimate container for your <a> tag. But anyway, doing it this way you get to write plain JavaScript without having to worry about the mess of quoting etc.

Related

Select2 Event for creating a new tag

I'm using the jQuery Select2 (v4) plugin for a tag selector.
I want to listen for when a new tag is created in the select element and fire an ajax request to store the new tag. I discovered there is the createTag event but this seems to fire every time a letter is entered into the select2 element. As shown in my fiddle: http://jsfiddle.net/3qkgagwk/1/
Is there a similar event that only fires when the new tag has finished being entered? I.e. it's enclosed by a grey box enclosing it.
I can't find any native method unfortunately. But if you're interested in simple "workarounds", maybe this get you closer:
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "],
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
// add indicator:
isNew : true
};
}
}).on("select2:select", function(e) {
if(e.params.data.isNew){
// append the new option element prenamently:
$(this).find('[value="'+e.params.data.id+'"]').replaceWith('<option selected value="'+e.params.data.id+'">'+e.params.data.text+'</option>');
// store the new tag:
$.ajax({
// ...
});
}
});
DEMO
[EDIT]
(Small update: see #Alex comment below)
The above will work only if the tag is added with mouse. For tags added by hitting space or comma, use change event.
Then you can filter option with data-select2-tag="true" attribute (new added tag):
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "]
}).on("change", function(e) {
var isNew = $(this).find('[data-select2-tag="true"]');
if(isNew.length && $.inArray(isNew.val(), $(this).val()) !== -1){
isNew.replaceWith('<option selected value="'+isNew.val()+'">'+isNew.val()+'</option>');
$.ajax({
// ... store tag ...
});
}
});
DEMO 2
The only event listener that worked for me when creating a new tag was:
.on("select2:close", function() {
(my code)
})
This was triggered for new tags and selecting from the list. change, select2:select, select2:selecting and any others did not work.
One more simple check will be this based on the difference in the args of the event .....
While I was dealing with this situation, I had seen this difference; that when the new element is created the event args data does not have an element object but it exists when selecting an already available option...
.on('select2:selecting', function (e) {
if (typeof e.params.args.data.element == 'undefined') {
// do a further check if the item created id is not empty..
if( e.params.args.data.id != "" ){
// code to be executed after new tag creation
}
}
})
Another workaround. Just insert it to the beginning:
}).on('select2:selecting', function (evt) {
var stringOriginal = (function (value) {
// creation of new tag
if (!_.isString(value)) {
return value.html();
}
// picking existing
return value;
})(evt.params.args.data.text);
........
It relies on underscore.js for checking if it's string or not. You can replace _.isString method with whatever you like.
It uses the fact that when new term is created it's always an object.

JS function to remove tag

I have added a button to TinyMCE using the following JS code:
(function() {
tinymce.PluginManager.add('button_span', function( editor, url ) {
editor.addButton('button_span', {
text: 'Test Button',
icon: false,
onclick : function() {
editor.selection.setContent('<em>' + editor.selection.getContent() + '</em>');
}
});
});
})();
So, when user clicks the button, it wraps any highlighted words into <em> tags.
My question is, how do I make it so that if the highlighted words are already in <em> tag, then it should remove the tag. I am guessing we need to adjust the onclick function.
Maybe give this a shot. I'm not very familiar with tinyMCE but this should work in general. Also, you'll want to expand this to check to see if there is also an '', and the replaces will vary based on that, this is just to get you started, but like I said, should be the basis of what your trying to do I think.
onclick : function() {
var contents = editor.selection.getContent();
if (contents.indexOf('<em>') >= 0) {
contents.replace('<em>', '');
contents.replace('</em>', '');
editor.selection.setContent(contents);
} else {
editor.selection.setContent('<em>' + editor.selection.getContent() + '</em>');
}
}

Running same JQuery function on many elements with same id

I'm sure this is going to be simple well i hope it is. After racking my brain for days I have finally sorted my last problem thanks you someone on here, But now I have a new problem. I am dynamically creating blogs hundreds of them. I'm using JQuery to load a editor into a simple modal window like so
<a class="blog_btns" id="edit" data-id="$b_blog_id" href="">Edit</a>
then the JQuery
jQuery(function($) {
var contact = {
message: null,
init: function() {
$('#edit').each(function() {
$(this).click(function(e) {
e.preventDefault();
// load the contact form using ajax
var blogid = $(this).data('id');
$.get("../_Includes/edit.php?blogid=" + blogid, function(data) {
// create a modal dialog with the data
$(data).modal({
closeHTML: "<a href='#' title='Close' class='modal-close'>x</a>",
position: ["15%", ],
overlayId: 'contact-overlay',
containerId: 'contact-container',
onOpen: contact.open,
onShow: contact.show,
onClose: contact.close
});
});
});
});
},
open: function(dialog) {
dialog.overlay.fadeIn(200, function() {
dialog.container.fadeIn(200, function() {
dialog.data.fadeIn(200, function() {
$('#contact-container').animate({
height: h
}, function() {
$('#contact-container form').fadeIn(200, function() {
});
});
});
});
});
},
show: function(dialog) {
//to be filled in later
},
close: function(dialog) {
dialog.overlay.fadeOut(200, function() {
$.modal.close();
});
},
};
contact.init();
});
the problem I have is i have hundreds of
<a class="blog_btns" id="edit" data-id="$b_blog_id" href="">Edit</a>
but I want the all to run the same jQuery function above.
Can anyone help? Is there a simple way of doing this?
...many elements with same id...
That's the problem, you can't have multiple elements with the same id.
You probably want to use a class:
<a class="blog_btns edit" data-id="$b_blog_id" href="">Edit</a>
<!-- Added ---------^ -->
Then:
$('.edit').each(...);
// ^---- ., not #, for class
But you probably don't want to use each, just do:
$('.edit').click(function(e) {
// ...
});
There's no need to loop through them individually.
Another approach you might consider is rather than hooking click on each individual "edit" link, you might want to use event delegation. With that, you hook the event on an element that contains all of these "edit" links (there's bound to be a reasonable one, body is always possible as a last resort), but tell jQuery not to notify you of the event unless it passed through one of these on its way to that element in the bubbling. That looks like this:
$("selector for the container").on("click", ".edit", function(e) {
// ...
});
Within the handler, this will still be the "edit" link.
Use class instead of id as according to HTML standards each element should have a unique id.
id: This attribute assigns a name to an element. This name must be unique in a document.
class: This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class name or
names. Multiple class names must be separated by white space
characters.
http://www.w3.org/TR/html401/struct/global.html
so use class instead of id
<a class="blog_btns edit" data-id="$b_blog_id" href="">Edit</a>
and refer to it with $('.edit')

jQuery $(this) does not insert text into my element

I am currently adding flagging functionality to a project of mine, and I can't get jQuery's $(this) selector to work.
The goal of this is to change the text in the div from flag to flagged when the user clicks it, and the ajax query runs successfully. My HTML/PHP is:
<div class="flag" post_to_flag='".$post_to_flag."'>Flag</div>
And my javascript that deals with the div is:
$('.flag').live('click', function () {
$.post('../php/core.inc.php', {
action: 'flag',
post_to_flag: $(this).attr('post_to_flag')
}, function (flag_return) {
if (flag_return == 'query_success') {
$(this).text('flagged');
} else {
alert(flag_return);
}
});
});
I can't replace the text with flagged, but if I replace the this selector with the .flag selector, it will replace everything with the class of flag on the page.
I have checked, and the $(this) selector is getting the attribute of 'post_to_flag' just fine. Why is this happening, and how can I fix it?
You should add a context variable:
$('.flag').live('click', function () {
var $context = $(this);
$.post('../php/core.inc.php', {
action: 'flag',
post_to_flag: $context.attr('post_to_flag')
}, function (flag_return) {
if (flag_return == 'query_success') {
$context.text('flagged');
} else {
alert(flag_return);
}
});
});
You are calling multiple functions within your jQuery selection call. When you go into that $.post() function, your scope changes. this now refers to a different scope from when you were inside one().
#Moak's suggestion, if you set a variable to a jQuery object, it's probably best to denote the variable with a beginning $ just for potential clarity for future readers or yourself.
this inside the ajax callback is not the element, but it is the Ajax object itself.
You can use $.proxy to pass in the context.
Ref $.proxy
$('.flag').live('click', function () {
$.post('../php/core.inc.php',
{action: 'flag', post_to_flag: $(this).attr('post_to_flag')},
$.proxy(function(flag_return) {
if(flag_return == 'query_success'){
$(this).text('flagged'); //Now this here will represent .flag
}else{
alert(flag_return);
}
},this)); //Now here you are passing in the context of `.flag`

Javascript scope question: Can't change element via 'this' obj passed to function, but I can using longhand approach

REVISED QUESTION (SEE BELOW FOR ORIGINAL):
Here is an example of a simple ajax load with an event binding on an element within the loaded content:
soTest.htm
<!DOCTYPE html>
<html>
<head>
<script language="JavaScript" type="text/javascript" src="http://code.jquery.com/jquery-1.6.min.js"></script>
<script>
function changeBG(obj)
{
alert('Color 1: Should Turn Red');
jQuery(obj).css('background-color','red');
alert('Color 2: Should Turn Green');
jQuery('#' + jQuery(obj).attr('id')).css('background-color','green');
}
jQuery(document).ready(
function() {
jQuery('.loadedContent').load('soTest2.htm');
jQuery('body').delegate("#theElem","click",
function(){
var obj = this;
jQuery('.loadedContent').load('soTest2.htm',
function(){
changeBG(obj);
}
);
});
}
);
</script>
</head>
<body>
<div class="loadedContent">
</div>
</body>
</html>
Ajax loaded content, soTest2.htm:
<div id="theElem" >
Hello
</div>
So why is it that this doesn't work:
jQuery(obj).css('background-color','red');
But this does:
jQuery('#' + jQuery(obj).attr('id')).css('background-color','red');
++++++++++ORIGINAL QUESTION:++++++++++
I have a table that I want to sort when specific table headings are clicked (those with the class "sort").
For instance:
Location
To do that I have this code:
jQuery('body').delegate("click", ".sort", function(event) {
event.preventDefault();
jQuery('.searchResults').html('<div align="center" style="margin-top:35px;"><img src="/common/images/ajax-loader_big.gif" /></div>');
var TimeStamp = new Date().getTime();
var sortItem = this;
jQuery('.searchResults').load('modules/configSearchResultsOutput.cfm?' + TimeStamp + '&sortby=' + jQuery(this).attr('sortby') + '&direction=' + jQuery(this).attr('direction'), {
data: jQuery('#results').val()
}, function() {
sortCallback(sortItem);
});
});
So on the click event for one of these sortable column headings I'm storing the entire 'this' scope in a var to pass through to this function.
To simplify the question I'll just say that we're trying to change the background color of the clicked element based on the custom attr 'direction' I'm using:
function sortCallback(obj) {
//Returns correct attribute value
alert('In Callback: ' + jQuery(obj).attr('direction'));
//Does not return correct attribute value -- almost like it's cached or something
alert('Long hand reference: ' + jQuery('.sort[sortby="' + jQuery(obj).attr('sortby') + '"]').attr('direction'));
//Must reference value via (obj) to get correct updated value
if (jQuery(obj).attr('direction') == 'asc') {
//Changing a value within the element via this longhand approach works
jQuery('.sort[sortby="' + jQuery(obj).attr('sortby') + '"]').css('background-color', 'red');
//Changing a value within the element via this shorter approach does not work
jQuery(obj).css('background-color', 'red');
}
else {
//Works
jQuery('.sort[sortby="' + jQuery(obj).attr('sortby') + '"]').css('background-color', 'green');
//Doesn't work
jQuery(obj).css('background-color', 'green');
}
}
I'm assuming I'm not understanding some aspect of javascript scoping (understanding 'this' has been very elusive to me).
Question summarized:
If I'm passing a var'd 'this' scope to a function why can't I change the aspects of the 'this' element, why must I drill down using the long way to change them?
A tricky question for me to articulate, hopefully I did a good enough job.
Thanks!
This is happening because your ajax call replaces the DOM element. obj refers to a DOM element that was in the DOM before you called .load, but was replaced. Another element with the same ID does exist, though! That's the one you're referring to with your 'longhand' method.
I think your problem is because that load call is asynchronous, causing jQuery to get confused. Put your code inside a callback for load and it should work:
jQuery(document).ready(function() {
jQuery('.loadedContent').load('soTest2.htm',
function(resp, status, xhr){
jQuery("#theElem").bind('click',
function(){
changeBG(this);
});
});
});

Categories