I have an sortable grid of elements, that updates its value to DB after user moves the element. The problem is, I don't know how to update the id of all previous elements to a new one without reloading the page.
In PHP, I would do something like this (code from FAQ of one of my older pages), but I can't use PHP (it has to happen without any page reloading, right after user places element he moved):
if ($old_order > $order){
$result = dbquery("UPDATE faq SET orders=orders+1 WHERE orders>='$order' AND orders<='$old_order'");
}else{
$result = dbquery("UPDATE faq SET orders=orders-1 WHERE orders>='$old_order' AND orders<='$order'");
}
I would like to do that with jQuery, basically I have 7 elements with id from 0 to 6 and every time user changes the position, I serialize it and send it with ajax to an php code that saves it.
What it does now:
Move elemtent 1 to position 4.
Saves and works.
Move element 3 to position 2
Moves element 1 from position 4 back to his old one, as the ID of it
is still 1 and not 4.
What I want to do:
Move element 1 to position 4
Change ID of element 1 from 1 to 4
Change ID of element 2, 3 and 4 by -1 to id 1, 2 and 3
I hope somebody understands me and can help me.
jQuery code I actauly use:
$(".content-page").sortable({
start: function(e,ui){
ui.placeholder.height($(".sorted-icons").outerHeight(true));
ui.placeholder.width($(".sorted-icons").outerWidth(true));
},
placeholder: 'placeholder',
items: '.sorted-icons:not(.new_icon)',
update: function(e,ui) {
var order = $(this).sortable("serialize") + '&order=icons' + '&content_id=' + $(this).attr("data-shortcut-id");
console.log(order);
$.post("page_ajax.php", order).done(function(data){
console.log(data);
}).fail(function(data){
console.log(data);
});
}
}).disableSelection();
Html code basically looks like this with content inside of that div thats irelevant:
echo "<div class='sorted-icons' id='icon_$id'>";
If you have any questions, just comment and Ill try to answer them and update the queston.
Fixed jQuery:
var i = 0;
$(this).children('.sorted-icons').each(function(){
$(this).attr('id', 'icon_' + i);
i++;
});
Still have problem with PHP part tho. Its saving them in weird orders.
Ok, so I had one little bug in my PHP code, but I managed to fix the jQuery with really simple pice of code:
$(".content-page").sortable({
start: function(e,ui){
ui.placeholder.height($(".sorted-icons").outerHeight(true));
ui.placeholder.width($(".sorted-icons").outerWidth(true));
},
placeholder: 'placeholder',
items: '.sorted-icons:not(.new_icon)',
update: function(e,ui) {
var order = $(this).sortable("serialize") + '&order=icons' + '&content_id=' + $(this).attr("data-shortcut-id");
console.log(order);
$.post("page_ajax.php", order);
// THIS PART //
var i = 0;
$(this).children('.sorted-icons').each(function(){
$(this).attr('id', 'icon_' + i);
i++;
});
// THIS PART //
}
}).disableSelection();
Hopefully might help somebody else.
Related
I using PhoneGap to create a Geolocation App following this excellent tutorial (link). Unfortunatelly, I'm having an issue that I can't figure out. The relevant parts that are giving me a headache are these:
//Section 1
$('#history').on('pageshow', function () {
tracks_recorded = window.localStorage.length;
$("#tracks_recorded").html("<strong>" + tracks_recorded + "</strong> workout(s) recorded");
$("#history_tracklist").empty();
for (i = 0; i < tracks_recorded; i++) {
$("#history_tracklist").append("<li><a href='#track_info' data-ajax='false'>" + window.localStorage.key(i) + "</a></li>");
}
$("#history_tracklist").listview('refresh');
});
//Section 2
$("#history_tracklist li a").on('click', function () {
$("#track_info").attr("track_id", $(this).text());
});
//Section 3
$('#track_info').on('pageshow', function () {
var key = $(this).attr("track_id");
$("#track_info div[data-role=header] h1").text(key);
var data = window.localStorage.getItem(key);
data = JSON.parse(data);
});
Section 1 works just fine, the data is stored, and the list is created without any issues. But then in Section 2 is when everything goes to hell. By clicking on the element, a new attribute (track_id) is supposed to be created, but it doesn't. Therefore, in Section 3, the "var key" won't get a value, and as a consequence, "var data" will be null also. As you can imagine, nothing works from there. What am I doing wrong here? I only included what I considered the relevant code, but if more is needed I'll do so. Thansk!
In section 2, I think you just need to delegate click handling to the "#history_tracklist" container, as follows :
$("#history_tracklist").on('click', "li a", function () {
$("#track_info").attr("track_id", $(this).text());
});
Without delegation you have a rule saying :
when any existing li a element within #history_tracklist is clicked execute my function
With delegation, you have a rule saying :
when any existing or future li a element within #history_tracklist is clicked execute my function
I'm attempting to make a menu bar that can have <li> elements added and removed. So far so good, but when I try and remove them I'm running into issues. I've toyed with this for a couple hours and now I'm wondering if this whole process could just be made easier (maybe an object?).
Anyways, here's the full code (80 lines), with comments to follow along.
var tabs = $('.accountSelectNav');
var titles = [];
var listItems = [];
// when the page loads check if tabs need to be added to the ul (menu bar)
$(document).ready(function(e) {
if ($.cookie('listItems') != null) {
console.log('not null');
//return "listItems" to it's array form.
listItems = JSON.parse($.cookie('listItems'));
$('.accountSelectNav').append(listItems);
}
});
$('.selectTable td:first-child').on('click', function(e) {
$('#home_select').removeClass('navHighlight');
//grab the text value of this cell
title = $(this).text();
$.ajax({
url:'core/functions/getAccountId.php',
type: 'post',
data: {'title' : title}
}).fail (function() {
alert('error');
}).done(function(data) {
accountId = $.trim(data);
// store values in the cookie
$.cookie('account_id', accountId, {expires : 7});
$.cookie('title', title, {expires : 7});
window.location = ('home_table.php');
});
// make sure the value is NOT currently in the array. Then add it
var found = jQuery.inArray(title, titles);
if (found == -1) {
titles.push(title);
addTab();
}
// make sure the value is NOT currently in the array. Then add it
found = jQuery.inArray(title, listItems);
if (found == -1) {
addListItem();
//place <li>'s in cookie so they may be used on multiple pages
$.cookie('listItems', JSON.stringify(listItems));
};
});
$("body").on("click", ".deleteImage", function (e) {
var removeTitle = $(this).closest('li').find('a').text();
var removeItem = $(this).closest('li')[0].outerHTML;
//remove title from "titles" array
titles = jQuery.grep(titles, function (value) {
return value != removeTitle;
});
//remove <li> from "listItems" array
listItems = jQuery.grep(listItems, function (value) {
return value != removeItem;
});
// this shows the <li> is still in the listItemsarray
console.log(listItems);
// put the array back in the cookie
$.cookie('listItems', JSON.stringify(listItems));
removeTab(this);
});
$("body").on("mouseover", ".accountSelectNav li", function(e) {
$(this).find('.deleteImage').show();
});
$("body").on("mouseleave", ".accountSelectNav li", function(e) {
$(this).find('.deleteImage').hide();
});
function addTab() {
tabs.append('<li class="navHighlight">' + '' + title + '' + '' + '<img src="images/delete.png" class="deleteImage"/>' + '' + '</li>');
};
function removeTab(del) {
$(del).closest('li').remove();
}
function addListItem() {
var s = ('<li class="navHighlight">' + '' + title + '' + '' + '<img src="images/delete.png" class="deleteImage"/>' + '' + '</li>');
listItems.push(s);
}
So you see I have two arrays of equal length that should always be the same length. One stores the title to be displayed in the tab, the other holds the html for the <li> which will be appended to the <ul>. I have no problem removing the title from its array. However removing the <li> from it's array is becoming a rather big hassle. You see when I get the <li> element after its been inflated the html inside does not exactly match what was put in, the browser adds style elements.
Example, the variable "removeItem" represents the html value of the selected <li> I wish to remove. It looks like this:
<li class="navHighlight">Test1<img src="images/delete.png" class="deleteImage" style="display: inline;"></li>
yet the value in my array "listItems" looks like this:
<li class="navHighlight">Test1<img src="images/delete.png" class="deleteImage"/></li>
So my attempt at removing it from my array always fails because they aren't a perfect match.
Now my question is how do I remove this <li> item? Also is there an easier way to do this whole process and I'm just not seeing it?
Thanks for your time.
EDIT
Fiddle by request here
Easiest way I can explain it.
Click the link to the fiddle.
Click any cell in the "App Name" column
This will add a <li> to the <ul> (menu) above of the table
When you hover over the <li> a picture appears
Click the picture
This should remove the <li>, both from the <ul> and from the array listItems
right now it does not
In the process of making this easier to check, I've taken your JSFiddle and did the following:
removed extra console.log and comments
removed interaction with cookies (since I did not have them in the first place, I figured they wouldn't just the first scenario)
After doing so I reached a point (you can see it here) where the desired functionality just works.
I even went ahead and removed the ajax stuff because that alert was driving me crazy. (here)
Since this works fine, my guess is that your issue lies between the lines that I removed.
Your usage of cookies is as follows:
To load existing tabs and add them back again
To save account_id and title, which is not used back again
To persist the listItems after a new item has been added
I then opened up the console with your version of the fiddle and the execution of javascript stops at $.cookie() with the error undefined is not a function.
This clearly indicates that the issue present in the Fiddle is that jQuery.cookie is not present and so those calls are halting the execution of the rest of your script. This also explains why it just started working when I took them out.
I posted the whole process of how I got there to indicate how I trimmed down the problem to specific parts, which is useful to reduce the problem space. When you're out of options and reach a place when you're lost, it's easier to post a question with less code and the specific part of the problem that you've identified. This will help you in finding the issues that you're facing and StackOverflow to provide proper answers to your questions.
Hope it helps!
Here is the solution I came up with. It should be much easier for people to understand than my original post. Although it's a long read it may be worth it, especially for new developers.
The point of this code is to make a menu bar out of an un-ordered list or <ul>. The menu bar needs to be used on multiple pages. So I'll be using cookies.
I start with this code to get a text value from my table.:
$('.selectTable td:first-child').on('click', function(e) {
// This value will be used later for the name of the tab or `<li>` inside our menu bar or `<ul>`
title = $(this).text();
});
Then I place the value in an array. I do this only if the array does not already have this string inside it. I do not want duplicates:
var found = jQuery.inArray(title, titles);
var titles = [];
if (found == -1) {
titles.push(title);
}
Then I store the array into a cookie, using a library like this:
$.cookie('titles', JSON.stringify(titles));
Now when any page loads that needs this menu bar I run this code to check if there are any values:
$(document).ready(function() {
if ($.cookie('titles') != null) {
titles = JSON.parse($.cookie('titles'));
}
});
Now I need to loop through the array. When I loop through the array I have to do 3 things:
1) Grab the string value.
2) Add the html to my new string so it becomes a list item or <li>.
3) Append the newly created <li> to our <ul>.
Like so:
for(var i = 0; i < titles.length; i++) {
var str = titles[i];
var listItem = '<li class="navHighlight">'
+ '<a href="#">'
+ str
+ '</a>'
+ '<a href="#">'
+ '<img src="images/delete.png" class="deleteImage"/>'
+ '</a>'
+ '</li>';
$('.accountSelectNav').append(listItem);
}
Now, if I want to remove this <li> I click the delete image found inside our <li>. What delete image you say? Look at the html I added again. You will see I add an <img> tag in there.
Now delete like so:
$("body").on("click", ".deleteImage", function (e) {
// grabs the text value of my li, which I want to remove
var removeTitle = $(this).closest('li').find('a').text();
// runs through my titles array and returns an array without the value above
titles = jQuery.grep(titles, function (value) {
return value != removeTitle;
});
});
Then I simply place the new array inside my cookie once again. Like this:
$.cookie('titles', JSON.stringify(titles));
And finally I remove the tab like this:
removeTab(this);
function removeTab(del) {
$(del).closest('li').remove();
}
Yay, I'm done. So now, if anyone has a more elegant way of accomplishing this I'm listening. I have no doubt there's a better way, javascript/jQuery isn't even close to my strong point.
The full code can be found here.
I have received help earlier in another question about some jQuery transitioning and I got my website to behave properly, but now I need to get a bit deeper into this jQuery transitioning...
I need a particular effect/transition to happen based on the hashtag that is written in the address bar. This is the code provided by the other question by pckill:
$('.nav').on('click', 'li', function(){
var id = $(this).data('id');
var breadcrumbs = document.getElementById('breadcrumbs');
breadcrumbs.innerHTML = 'IMGit » <span class="capitalize">' + id + '</span>';
var current = $('#inner').find('[data-page=' + id + ']');
if (current.hasClass('hidden'))
{
current.css('marginLeft', '-200%');
$('#inner > div').not(current).animate(
{marginLeft: '100%'},
'fast',
function(){
$('#inner > div').not(current).addClass('hidden');
current.removeClass('hidden');
current.animate({marginLeft: '0%'}, 'fast');
});
}
});
And this is the HTML: http://pastebin.com/pu7jmefC
Let's say, for example, I link someone to http://mywebsite.com/index.php#remote, I want the user to be transitioned with jQuery to the proper div. The approach above works perfectly with the menu I have, but I want to be able to share the URL with someone and they'd still be able to get directly to the proper div.
I think the code above needs some altering to make it do what I seek, but I unfortunately, I'm not that good in Javascript/jQuery.
I guess we'd have to touch the code somewhere around here: $('#inner > div').not(current).
I know we have window.location.hash to work with hashtags, but I have no idea how to put it to use in the code above.
Ideas?
If you just need to check the hash on page load and perform an action accordingly, that's really simple. First of all you need to move the logic of transitioning to a div into a separate function, say transitionToDiv:
function transitionToDiv(id) {
var current = $('#inner').find('[data-page=' + id + ']');
if (current.hasClass('hidden'))
{
current.css('marginLeft', '-200%');
$('#inner > div').not(current).animate(
{marginLeft: '100%'},
'fast',
function(){
$('#inner > div').not(current).addClass('hidden');
current.removeClass('hidden');
current.animate({marginLeft: '0%'}, 'fast');
});
}
}
And change the click event (the code in your question) to:
$('.nav').on('click', 'li', function() {
var id = $(this).data('id');
var breadcrumbs = document.getElementById('breadcrumbs');
breadcrumbs.innerHTML = 'IMGit » <span class="capitalize">' + id + '</span>';
transitionToDiv(id);
}
Now, to transition to a div on page load based on the address hash, simply add these lines at some point after page load:
var id = window.location.hash.substr(1);
transitionToDiv(id);
This is the sequel to this thread:
4 toggle buttons speak javascript to each other but none of them are good listeners
Our heros have overcome the ridiculous amount of nonsense originally presented in the fiddle http://jsfiddle.net/EjW7A/8/ (no longer available) when #nbrooks -reinvigorated by the forces of good- conquered all of the stupidly placed arrays, functions and the mammoth amount of redundant content with his solution:
http://jsfiddle.net/EjW7A/24/
We rejoin Luhring after 8 hours of poking, prodding, red bull drinking, concrete wall head-bashing at the final step of solving the epic problem of doom- implementation:
The new fiddle:
http://jsfiddle.net/Luhring/EjW7A/38/
Problem:
How can I insert the content dynamically- allowing each button to toggle it's own content while making sure the other buttons are toggled off and their content hidden? ex, if button 1 is toggled on (it is animated as if it were a 'real' pressed button), button 1s content is displayed in a gallery where the contents can be clicked to display a lightbox. when button 2 is clicked should toggle button 1 off and replace button 1's contents with its own.
New Working Demo
Anything invoking jQuery on DOM elements must be wrapped within the DOM ready function to work correctly (this is why your $('a').click() was failing. Also, normally if you see yourself creating multiple arrays that you never end up using, and still end up referencing each element directly, you're making a lot of wasted effort. I cleaned your code up a bit - take a look:
jQuery(document).ready(function($) {
//variable declaration section.
var contentArray = ['albumArt', 'logoDesign', 'UX', 'other'],
content = {}, newClassName, $selectedArray, i;
for ( i = 0; i < contentArray.length; i++) {
var className = contentArray[i];
content[className] = $('.' + className);
}
//prevent links that are clicked from going anywhere
$("a").click(function(e) {
e.preventDefault();
});
$('.workTypes').click(function() {
if ($(this).is('#centeringDiv a')) return;
$(this).toggleClass('workTypesSelected');
$('.workTypesSelected').not(this).removeClass('workTypesSelected');
$selectedArray = content[$('.workTypesSelected').attr('id')];
$('#galleryDiv').empty();
if ( $selectedArray ) {
// note creates #largeGallery elements dynamically
for ( i = 0; i < $selectedArray.length; i++ ) {
var $selected = $selectedArray.eq(i);
$('<a>').attr({
href: $selected.attr('href'),
title: $selected.attr('title'),
class: "lb_gal"
}).append(
$('<img>').attr({
id: "largeGallery"+i,
src: $selected.attr('href'),
class: "gallery cf"
}).rlightbox()
)
.appendTo('#galleryDiv')
.rlightbox();
}
}
}); // end click handler
}); //end the document ready jquery function
Before you -1 this for being such a simple question read further, because ive spent a while searching and cant figure it out. What i have is 5 select boxes. Each ones results depend on what is selected before it. There is no submit button. I just need the to change based on whats selected in the previous box and so far i have that. Oh and the results are being pulled from a database. The problem is when you select an option in lets say box 1, box 2 options appear, but when you go and select an option in box 1 again, they options are just stacked on the others. I need them to clear when its changed again. I'll post the js i have and if you need anything else just ask.
p.s. im getting the options using php-mysql.
p.s.s this site has to be finished by tomorrow so im kinda in a rush. Please dont waste time telling me this is a stupid question or what not.
Thanks in advance for the help.
$(function () { //When the page is finished loading run this code
$('#country').change(function () {
$.ajax({
url: "<!--Base url taken out-->/discovery/aLoad",
success: function (data) {
eval(data);
},
error: function () {
alert('failed');
},
data: {
country: getSelectValues('#country')
},
type: 'POST'
});
});
});
function changeSearchBar (newBar) {
//remove the crap
function ClearOptions(country)
{
document.getElementById('country').options.length = 0;
}
for (var i = 0; i <= newBar.length; i++) {
newBar[i].id = newBar[i][0];
newBar[i].name = newBar[i][1];
$('#group').append(
$('<option></option>').attr('value', newBar[i].id).text(newBar[i].name)
);
}
}
function getSelectValues (sId) {
var str = "";
$(sId +" option:selected").each(function () {
str += $(this).val() + ",";
});
return str.replace(/.$/g, '');
}
From what I understand from your long post you just need to remove all select child's before starting to append the new option from the AJAX request.
Try something like this before your for loop:
$('#group').html('');
Demo: http://jsfiddle.net/57TYu/2/
Here you go, I think this is basically what you are trying to do:
How do you remove all the options of a select box and then add one option and select it with jQuery?
Basically, find the 'option' tags inside the select and remove them.
$('select').find('option').remove()
will clear all the select boxes.
This will append the data, which is assume are the options in their place:
$('select').find('option').remove().end().append(data);
I think that is what you are looking for.