jquery prop multiple items? - javascript

I'm not sure what I'm doing wrong but for the past 2 hours I've been trying to use prop to change the value of two items in a button. It works for one but not for the other and I have no idea why.
html:
<input type='button' value='Following' id='btnFollow' dataaction="UnFollow" datatype='topic'>
jquery:
$("#btnFollow").prop("value", "Follow");
$("#btnFollow").prop("dataaction", "Follow");
The first item changes(value) but not the second one(dataaction). I have no idea why(other then maybe its too late and my brain is rebelling). According to the documentation I'm doing it correct. I added alerts inbetween each command in case one was failing, but both alerts went off meaning jquery is not crashing or anything when it tries to change the second item. I don't see any spelling mistakes and I tried to daisy chain the commands but still no luck.
Any suggestions?
entire_code:
$(document).ready(function () {
$('#btnFollow').click(function() {
var topic_id = $(this).attr('datatopic');
var action_type = $(this).attr('datatype');
var action_type_action = $(this).attr('dataaction');
alert(action_type_action);
//$("#btnFollow").prop('value', 'Following');
if (action_type_action == 'Follow') {
$("#btnFollow").prop({'value': 'Following', 'dataaction': 'UnFollow'});
//$("#btnFollow").prop("value", "Following");
//$("#btnFollow").prop("dataaction", "UnFollow");
$.ajax({
type: 'POST',
url: '/follow_modification',
async: false,
data: {
topic: topic_id,
action: action_type_action,
follow_type: action_type
}
//complete: function(xmlRequestObject, successString){
// ymmReceiveAjaxResponse(xmlRequestObject, successString);
//}
});
} else if (action_type_action == 'UnFollow') {
$("#btnFollow").prop({'value': 'Follow', 'dataaction': 'Follow'});
//$("#btnFollow").prop("value", "Follow");
//$("#btnFollow").prop("dataaction", "Follow");
$.ajax({
type: 'POST',
url: '/follow_modification',
async: false,
data: {
topic: topic_id,
action: action_type_action,
follow_type: action_type
}
//complete: function(xmlRequestObject, successString){
// ymmReceiveAjaxResponse(xmlRequestObject, successString);
//}
});
}
})
});

Your code works just fine: http://jsfiddle.net/zerkms/Capvk/
Properties generally affect the dynamic state of a DOM element without changing the serialized HTML attribute
http://api.jquery.com/prop/
So that's why you don't see it changed in html, but it is changed in DOM instead. If you want it to be changed in HTML as well - use .attr()
PS: as #ahren mentioned in the comments - it probably makes sense to use .data() and data-xxx properties
PPS: if you set the value using .prop() - you need to get it with .prop() respectively

If there is a need to set multiple properties with single jQuery .prop method,
just try this:
instead
$("#btnFollow").prop("value", "Follow");
$("#btnFollow").prop("dataaction", "Follow");
use
$("#btnFollow").prop({"value": "Follow", "dataaction": "Follow"});

Please use .attr jQuery method.
Please use properly html5 data attribute asenter code here data-action for which you have new jQuery method to access this data attribute with $('#btnFollow').data('action') For more details visit

Related

Ajax jQuery Multiple Step Form instead of reloading div, just append new content

I wonder if it's possible to do this multistep form on one single page, so not reloading the div with the content received from the php file but append it right below..
This is what I've got so far:
$(document).on('submit', '#reg-form', function(){
var ln = $('#submit').val();
var id = $('#id').val();
var data = 'submit='+ln;
$.ajax({
type: 'GET',
url : 'step.php',
dataType : 'html',
data : data,
success : function(data)
{
$('#reg-form').fadeOut(500).hide(function()
{
$('.result').fadeIn(500).show(function()
{
$('.result'+id).append(data);
});
});
}
});
return false;
});
Also I tried to use different divs, with incremental id's to put every content in it's own div. The Problem is, I'm only getting the "second" step, so it's not going through the whole formular.
I guess it's because the form of the first page is still there and all have the same id.. Can anyone help me out here please?
id of element in document should be unique. Change the duplicate id at html source or using javascript
success : function(data) {
// change duplicate `reg-form` `id` to value
// corresponding to `.length` of elements having `id`
// containing `"reg-form"`
$(data).filter("#reg-form")
.attr("id", "reg-form-" + $("[id*='reg-form']").length);
$("#reg-form").fadeOut(500).hide(function() {
$(".result").fadeIn(500).show(function() {
$(".result" + id).append(data);
});
});
}

Make an array with all classes of an SVG element

I know this may look like a repost, but I am not able to get the code to work that the community made here.
What I am trying to do is make an array of all the classes listed in the element I am clicking on.
The element I am clicking on is a <g></g> element from a SVG object.
I would like to post the classes (in an array) to a modal and the ID of the <g> element. Here is my code:
//reveal Modal when when clicking on an item box.
$(document).ready(function() {
$('.items').click(function() {
$.ajax({
type: "POST",
url: "/includes/functions/choose_item.php",
data: { id: this.id, class: this.className}
})
.done(function() {
$('#choose_item_modal').foundation('reveal', 'open', "/includes/functions/choose_item.php") ;
})
});
});
It post it to my PHP script, and the ID works, but the class is in an array of baseval and animval, and I would like an array of all values of the baseval only.
This is the array I get:
Array ( [animVal] => items hero_item [baseVal] => items hero_item )
Thanks for any help.
SVG elements doesn't really have classes like regular elements, and the className property returns a special object, usually a SVGAnimatedString looking like
{animVal: "class class2", baseVal: "class class2"}
The class attribute is really just a regular attribute with some strangeness, so you need to use getAttribute('class') instead, or in jQuery attr() to get the value of the attribute
$(document).ready(function() {
$('.items').click(function() {
$.ajax({
type : "POST",
url : "/includes/functions/choose_item.php",
data : {
id : this.id,
'class' : $(this).attr('class')
}
}).done(function() {
$('#choose_item_modal').foundation('reveal', 'open', "/includes/functions/choose_item.php") ;
});
});
});
note that class is a keyword in javascript, so it should be quoted.
If you need an array, you can do $(this).attr('class').split(/\s+/);
TEST

How do you refresh an HTML5 datalist using JavaScript?

I'm loading options into an HTML5 datalist element dynamically. However, the browser attempts to show the datalist before the options have loaded. This results in the list not being shown or sometimes a partial list being shown. Is there any way to refresh the list via JavaScript once the options have loaded?
HTML
<input type="text" id="ingredient" list="ingredients">
<datalist id="ingredients"></datalist>
JavaScript
$("#ingredient").on("keyup", function(event) {
var value = $(this).val();
$.ajax({
url: "/api/ingredients",
data: {search: value.length > 0 ? value + "*" : ""},
success: function(ingredients) {
$("#ingredients").empty();
for (var i in ingredients) {
$("<option/>").html(ingredients[i].name).appendTo("#ingredients");
}
// Trigger a refresh of the rendered datalist
}
});
});
Note: In Chrome and Opera, the entire list is only shown if the user clicks on the input after entering text. However, I'd like the entire list to appear as the user types. Firefox is not a problem, as it appears to refresh the list automatically when the options are updated.
UPDATE
I'm not sure this question has a satisfactory answer, as I believe this is simply a shortcoming of certain browsers. If a datalist is updated, the browser should refresh the list, but some browsers (including Chrome and Opera) simply do not do this. Hacks?
Quite a long time after question but I found a workaround for IE and Chrome (not tested on Opera and already OK for Firefox).
The solution is to focus the input at the end of success (or done) function like this :
$("#ingredient").on("keyup", function(event) {
var _this = $(this);
var value = _this.val();
$.ajax({
url: "/api/ingredients",
data: { search: value.length > 0 ? value + "*" : "" },
success: function(ingredients) {
$("#ingredients").empty();
for (var i in ingredients) {
$("<option/>").html(ingredients[i].name).appendTo("#ingredients");
}
// Trigger a refresh of the rendered datalist
// Workaround using focus()
_this.focus();
}
});
It works on Firefox, Chrome and IE 11+ (perhaps 10).
I had the same problem when updating datalist.
The new values would not show until new input event.
I tried every suggested solutions but nothing using Firefox and
updating datalist via AJAX.
However, I solved the problem (for simplicity, I'll use your example):
<input type="text" id="ingredient" list="ingredients" **autocomplete="off"**>
<datalist id="ingredients"></datalist>
$("#ingredient").on("**input**", function(event) { ....}
Autocomplete and input is the couple that solve my problems and it works with Chrome too.
You can probably eliminate the problem if you don't make AJAX request on every key stroke. You can try throttle technique using set/cleatTimeout to issue request after 500ms after the last char typed:
$("#ingredient").on("keyup", function(event) {
clearTimeout($(this).data('timeout'));
$(this).data('timeout', setTimeout($.proxy(function() {
var value = $(this).val();
$.ajax({
url: "/api/ingredients",
data: {search: value.length > 0 ? value + "*" : ""},
success: function(ingredients) {
$("#ingredients").empty();
for (var i = 0; i < ingredients.length; i++) {
$("<option/>").html(ingredients[i].name).appendTo("#ingredients");
}
}
});
}, this), 500));
});
Yoyo gave the correct solution, but here's a better way to structure your inserts into the DOM.
$("#ingredient").on("keyup", function(event) {
var _this = $(this);
var value = _this.val();
$.ajax({
url: "/api/ingredients",
data: { search: value.length > 0 ? value + "*" : "" },
success: function(ingredients) {
var options = ingredients.map(function(ingredient) {
var option = document.createElement('option');
option.value = ingredient.name;
return option;
});
$("#ingredients")
.empty()
.append(options);
// Trigger a refresh of the rendered datalist
// Workaround using focus()
_this.focus();
}
});
Less DOM manipulation
With this refinement, I'm only inserting into the DOM a single time per each successful callback. This cuts down on the browser needing to re-render, and will help improve any "blips" in the view.
Functional Programming and Less Idiomatic jQuery
Here we are using the Array.prototype.map to clean up some of the jQuery and make things a bit less idiomatic. You can see from the ECMA Chart that this function will work in all browsers you are targeting.
Not Hacky
This by no means is hacky. IE appears to be the only browser that doesn't automatically refresh the input to display the new list options. focus() is just a way to ensure the input is refocused which forces a refresh of the view.
This solution works very well in all of the browsers that my company has to support internally, IE10+ Chrome and Firefox.
Place your #ingredients element is inside #container and try this code:
$.ajax({
url: "/api/ingredients",
data: {search: value.length > 0 ? value + "*" : ""},
success: function(ingredients) {
$("#ingredients").remove();
var item = $('<datalist id="ingredients"></datalist>');
for (var i in ingredients) {
item.append("<option>"+ ingredients[i].name +"</option>");
}
item.appendTo('#container');
}
});
even better without #container and using jQuery replaceWith():
$.ajax({
url: "/api/ingredients",
data: {search: value.length > 0 ? value + "*" : ""},
success: function(ingredients) {
var item = $('<datalist id="ingredients"></datalist>');
for (var i in ingredients) {
item.append("<option>"+ ingredients[i].name +"</option>");
}
$("#ingredients").replaceWith(item);
}
});
Your issue is that the AJAX is asynchronous.
You'd actually have to have a callback for the AJAX which you call onSuccess which would then update the datalist. Of course, then you might not have great performance/still have a "skipping" behavior, where your datalist options are lagging behind.
If your list of items from the AJAX isn't too large, you should:
1. load the ENTIRE list into memory array with the first query, then...
1. use a filtering function that is applied to the array each time you have a keyUp event.
I found a solution tested only on GNOME Web (WebKit) that consist on set the 'list' attribute of the input element to empty string and, inmediately after, set it again with the id of the datalist element. Here is the example, supose that your input element is stored in a variable named input_element:
var datalist = document.getElementById(input_element.list.id);
// at this point input_element.list.id is equals to datalist.id
// ... update datalist element here
// And now the trick:
input_element.setAttribute('list','')
input_element.setAttribute('list',datalist.id)

How to use HTML5's localstorage with Jquery's select2 plugin

Is there a way to use HTML5's localstorage method with Jquery's select2 plugin? Right now when I enter data and close the browser/tab, all entered data is gone, which is not so optimal since it can get confusing if you dont remember what you've entered
My select2 code looks like this:
$(".select").select2({
minimumInputLength: 1,
multiple: true,
query: function(query){
$.getJSON( 'url path to remote API', {
name:query.term,
featured:true
}, function(results){
var data = {results: []};
$.each(results.data, function(index, item){
data.results.push({id: item.artist_id, text: item.name});
});
query.callback(data);
} );
}
});
Any help is very appreciated
give this a try: http://jsfiddle.net/7267rkxy/12/
I commented the code for you for some explanation of what's going on, you should be able to just swap out the data option with your query option and it should still work
PS: I noticed none of your answered questions have been marked 'accepted', if someone gives you an answer that you like or that works for you, you should mark their answer 'accepted' by clicking the checkbox next to the answer
HTML
<!-- setting a hard width for example -->
<input type="text" class="select" style="width:200px;" value="" />
JS
// set value property to local storage value
$(".select").val(localStorage.s2options);
$(".select").select2({
minimumInputLength: 1,
multiple: true,
data: [{id: 1, text: 'option1'},{id: 2, text: 'option2'},{id: 3, text: 'option3'}], //sample data
initSelection: function (element, callback) {
// initSelection only fires when there is something in the value property
callback($.parseJSON(element.val()));
}
}).on('change', function(info){
// checking if we have anything stored in local storage
var s2options = localStorage.s2options ? JSON.parse(localStorage.s2options) : [];
// add / remove options
if (info.added) {
s2options.push(info.added);
} else if (info.removed) {
s2options = s2options.filter(function(opt) {
return opt.id != info.removed.id;
});
}
// save selections to local storage
localStorage.s2options = JSON.stringify(s2options);
});
In addition to #bruchowski 's answer, the newer version of Select2 has a different way of doing this (initSelection and query are still supported for backwards compatibility though):
You have to create a custom DataAdapter and implement current() and query().

Are element added by .append() already ready after appended?

I am building a kind of infinite scroll with jquery, but I am facing a DOM ready problem.
var n = 0;
// When user wants to load more, call this
function load_10_images(){
var g; var images = '';
for(g=1; g<=10; g++){
// Create images
images = '<div id="'+n+'" >'+
'<li id="li'+n+'">'+
'<img id="img'+n+'" src="images/loading.gif" />'+
'</li>'+
'</div>';
// add to html
$("#list").append(images);
// change source
$.ajax({
type: "POST",
url: "data.php",
data: {link_n: n},
success: function(resp) {
$("#img"+n).attr("src", resp);
},
});
// ...
n++;
}
}
My problem is images sources don't change. How to solve this problem ?
Your problem is scope. You create the DIVs and IMG ids with n as you loop through it. But you access the value of n in your ajax callback. So it will attempt to find $("#img"+n).attr("src", resp); with whatever the current value of n is (most likely the final value since it will finish faster than the post returns);
The problem is that since AJAX is async, your variable n inside the success call is equal to the variable n inside the last loop. Add a closure like that :
(function(int){
$.ajax({
type: "POST",
url: "data.php",
data: {link_n: int},
success: function(resp) {
$("#img"+int).attr("src", resp);
},
});
})(n);
As many people have pointed out, you have other issues that are causing the problems that you are seeing, but to answer your actual question, yes, they are available after .append(). Actually, what you find people do, frequently, is actually make the element available before appending it. In your code (since you're using jQuery), you could do that like this:
images = $('<div id="'+n+'" >'+
'<li id="li'+n+'">'+
'<img id="img'+n+'" src="images/loading.gif" />'+
'</li>'+
'</div>');
At that point, the element exists and can be read, modified, etc., but simply has not been added to the DOM yet.

Categories

Resources