show hide on logic js - javascript

I have some logic
$("#finish-button").click(function () {
$(".hidebuttonvresults").hide();
$(".showbuttonvresults").show();
});
This works for most of my pages, however one page does not have #finish-button. The only unique is id is #question-number but I only want this action to happen when the ID prints Question 15 of 15.
Any idea how to alter my logic to include this extra factor? I was trying
var str = $('#question-number').html();
if (str.indexOf("Question 40 of 46") !== -1) {
$(".hidebuttonvresults").hide();
$(".showbuttonvresults").show();
}
but it does not work

Related

Cant hide items per page and pagination in datatable when less then number displayed

I have a Datatable which if 1 page is returned i want to hide the 'Items per pages' dropdown list and also the pagination. This also needs to work when filtering the table.
I am using the:
.DataTable().page.info()
Below is the code i have
"fnDrawCallback": function () {
var accountSearchDataTableInfo = $('#accountSearchDataTable').DataTable().page.info();
if (accountSearchDataTableInfo.pages == '1') {
console.log(accountSearchDataTableInfo.pages == '1')
$('#accountSearchDataTable_length').hide();
$('#accountSearchDataTable_paginate').hide();
}
if (accountSearchDataTableInfo.pages == 1) {
console.log(accountSearchDataTableInfo.pages == 1)
$('#accountSearchDataTable_length').hide();
$('#accountSearchDataTable_paginate').hide();
}
}
And this gives...
Initial table load table info
Filtered table info
As you can see from my IF i have tried a number and string but when i do console.log on these it comes back true but the items are still displayed.
I have tried .hide() and also .css('display', 'none') but nothing seems to be working and i'm at a loss what else to try.
When i look at the element in Dev tools the style attribute is added but nothing after it:
Initial table load
Filtered table
Found the solution. I was looking for the parent DIV but it appear that if i used each individual identifier i can hide them. so my IF now look like
if (accountSearchDataTableInfo.pages == '1') {
$('.mb-2').hide(); // Items per page DD
$('#accountSearchDataTable_previous').hide(); // Pagintator 'Previous' button
$('#accountSearchDataTable_next').hide(); // Pagintator 'Next' button
$('.paginate_button').hide(); // Pagintator page '1' button
}
You can use below api to determine pages number
table.api().page.info().pages
As stated in documentation:
https://datatables.net/reference/api/page.info()
And use drawCallback() after table is draw As documented here:
https://datatables.net/reference/option/drawCallback
Example how to hide pagination when page is 1 or less:
$('#example').dataTable( {
"drawCallback": function( settings ) {
var api = this.api();
var pagination = $(this).closest('.dataTables_wrapper').find('.dataTables_paginate');
pagination.toggle(api.page.info().pages > 1);
}
} );

How to write a neat JS if else statement to dynamically add a nested Rails simple_form via Cocoon?

I am building a nested simple_form_for in rails using cocoon to dynamically add and remove nested elements. The main model object is a quote and a quote has many employees. I've reached the limit of my amateur code skills and would like some guidance on writing a neat js script so to achieve the following:
if nested_object.count <= 2 then remove_empee_link.hide
if nested_object.count > 2 then remove_empee_link.show, but not on the first two nested_objects.
if nested_object.count > 10 then add_empee_link.hide, otherwise always add_empee_link.show
Adapted from a really helpful post here courtesy of #nathanvda I've got to here;
$(document).ready(function() {
function check_to_hide_or_show_add_empee_link() {
if ($('#empee-form .nested-fields:visible').length == 5) {
$('#empee-form .links a').hide();
} else {
$('#empee-form .links a').show();
}
}
$('#empee-form').on('cocoon:after-insert', function() {
check_to_hide_or_show_add_empee_link();
});
$('#empee-form').on('cocoon:after-remove', function() {
check_to_hide_or_show_add_empee_link();
});
check_to_hide_or_show_add_empee_link();
});
$(document).ready(function() {
function check_to_hide_or_show_remove_empee_link() {
if ($('#empee-form .nested-fields:visible').length <= 2) {
$('.remove_fields').hide();
} else {
$('.remove_fields').show();
}
}
$('#empee-form').on('cocoon:after-insert', function() {
check_to_hide_or_show_remove_empee_link();
});
$('#empee-form').on('cocoon:after-remove', function() {
check_to_hide_or_show_add_remove_empee_link();
});
check_to_hide_or_show_add_remove_empee_link();
});
But I'm struggling to put a strategy together on how I can I achieve what I outlined in my biullets above in a neat solution, any guidance would be really appreciated after starting and playing with this for hours. Thanks
The updated code that I've now written, but the behavior is unexpected;
If 1, 2 or 3 nested elements on page, then all remove_links hidden.
If 4 nested elements on page then 1st, 2nd & 4th have remove_link hidden
If 5 nested elements on page then 1st, 2nd & 3rd have remove_link hidden
Intended behaviour, 1st and 2nd remove_links hidden always, anoy others shown:
// Hiding the 1st 'remove employee' link for the first two employee fields.
$(document).ready(function() {
function hide_first_and_second_remove_empee_links() {
var remove_links = $('.remove_fields')
$(remove_links[0]).hide();
$(remove_links[1]).hide();
// $('a.remove_fields:first-child').hide();
// $('a.remove_fields:nth-child(2)').hide();
}
$('#empee-form').on('cocoon:after-insert', function() {
hide_first_and_second_remove_empee_links();
});
$('#empee-form').on('cocoon:before-insert', function() {
hide_first_and_second_remove_empee_links();
});
hide_first_and_second_remove_empee_links();
});
How can this be? There's one method, it collects all .remove_fields' into the remove_links var, then wraps the[0]element of that collection in a jQuery object and callshideon it. Then the same to the1element. That method is called on page ready and then again oncocoon:before-insertandafter-insert. I don't see how the definition of the[0]and the1` elements changes?
Your logic becomes easier when you write:
always hide the first two remove links
hide the add association link if there are more than 10 employees
The second is already covered in your answer.
The first one is actually pretty easy using jquery:
$('.remove-fields:first-child').hide()
$('.remove-fields:nth-child(2)').hide()

jQuery - remove li from array with delete image

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.

adding class to array elements through loop

I need the loop that checks input fields from 'inputs' array, and if there are empty fields, special dialog need to be displayed near them, and after the dialog is displayed I need class 'style' to be added to the input field near which the dialog was displayed, then dialog should go to the next emppty field and add class 'style' to it. And so on until all empty inputs have class 'style'.
The problem is, in my loop after the dialog is displayed class 'style' is added only to the last element from the array, but it should be added to every empty element with delays in between.
This is my loop, but as I said it is not working properly:
for(i=0;i<inputs.length;i++){
var now = inputs[i];
var top = inputs[i].attr('top');
if(!now.val()){
if(dialog.css('display')=='none'){now.addClass('style');dialog.css('top',top).fadeIn(200);}
else{dialog.delay(300).animate({"top": top}, 500, function(){now.addClass('style');});
}else{now.removeClass('style');}}
P.S. Sorry for my English.
This is happening because the function that is calling 'addClass' is happening after the 300 millisecond animation. By that time, the value of the 'i' variable has changed because the for loop will continue to run.
You may just be able to have the 'now.addClass' call before the 'animate' and delay. Otherwise, you will have to break the loop and continue after the animation is complete to prevent the variable from being overwritten.
Here is an example of what I was talking about. The code below will process 1 input at a time and not continue to the next until the current one is finished processing (this code has not been tested):
var offset = -1;
var inputs = (something goes here)
iterateInputs();
function iterateInputs()
{
offset++;
if (typeof inputs[offset] != 'undefined')
{
eachInput();
}
else
{
// all done!
}
}
function eachInput()
{
var now = inputs[offset];
var top = inputs[offset].attr('top');
if (!now.val())
{
if (dialog.css('display')=='none')
{
now.addClass('style');
dialog.css('top', top).fadeIn(200, function(){
iterateInputs();
});
}
else
{
dialog.delay(300).animate({"top": top}, 500, function(){
now.addClass('style');
iterateInputs();
});
}
}
else
{
now.removeClass('style');
iterateInputs();
}
}

JQuery/Javascript works on & off

I am using JQuery 1.3.2-min in a project to handle JavaScript animations, ajax, etc. I have stored the file on the same server as the site instead of using Google. When I run the site locally on my development machine, everything works fine in FF, IE, Opera, and Safari (all the latest versions - I work from home and I only have 1 machine for personal use and development use) except for some CSS differences between them and when I go to the live site on my machine it works fine also. I have cleared my caches and hard refreshed the page, and it still works.
This is where it gets interesting however. When I send the site to my boss to test in various OS/Browser configurations, one page doesn't work correctly, some of it works, some doesn't. Also, the client (who uses IE 8) has also confirmed that it is not completely working - in fact he has told me that the page will work fine for a hour, and then just "turn off" for a while. I have never heard of this sort of thing before, and google isn't turning too much up. I have a hunch it may partly be with JQuery's .data(), but I'm not sure.
The page is basically nested unordered lists, and three basic actions happen on the list.
The top most unordered list is set to visible (all list via css are set to display: none to keep them hidden on a fresh page request); all list items divs are given a hover action of full opacity on mouseon, and faded back to 50% opacity on mouseoff; and then whenver a paragraph is clicked, the top most unordered list in that list item is displayed.
Here is my Javascript file for the page:
$(function() {
// Set first level ul visible
$('div#pageListing ul:first').css('display', 'block');
// Disable all the hyperlinks in the list
$('div#pageListing li a').click(function() {
var obj;
obj = $(this).parent(0).parent('div:first');
highlight(obj);
return false;
});
// List Item mouse hovering
$('#pageListing li').hover(
// Mouse On
function() {
if ($(this).children('div').attr('id') !== 'activePage') {
$(this).children('div').css('opacity', 1).css('filter',
'alpha(opacity=100)');
}
}, // Mouse off
function() {
if ($(this).children('div').attr('id') !== 'activePage') {
$(this).children('div').css('opacity', 0.4).css('filter',
'alpha(opacity=40)');
}
});
// Active list item highlighting
$('#pageListing li div').click(function() {
highlight($(this));
});
// Sub-list expanding/collapsing
$('#pageListing p.subpageslink').click(function() {
// Get next list
var subTree = $(this).parent('div').next('ul');
// If list is currently active, close it, else open it.
if (subTree.data('active') != true) {
subTree.data('active', true);
subTree.show(400);
} else {
subTree.data('active', false);
subTree.hide(400);
}
});
// Double clicking of list item - edit a page
$('#pageListing li div').dblclick(function() {
var classes = $(this).attr('class');
var classArray = classes.split(' ');
var pageID = classArray[1];
editPage(pageID);
});
// Handle button clicking
$('button#addPage').click(function() {
addPage();
});
$('button#editPage').click(function() {
var div = $('div#activePage');
var classes = div.attr('class');
var classArray = classes.split(' ');
var pageID = classArray[1];
editPage(pageID);
});
$('button#delPage').click(function() {
var div = $('div#activePage')
var classes = div.attr('class');
var classArray = classes.split(' ');
var pageID = classArray[1];
delPage(pageID);
});
});
// Highlighting of page when clicked
function highlight(obj) {
// Get previous hightlighted element
// and un-highlight
var oldElement = $('div#activePage');
oldElement.css('background', 'white');
oldElement.css('opacity', 0.4).css('filter', 'alpha(opacity=40)');
oldElement.removeAttr('id');
// highlight current selection
obj.attr('id', 'activePage');
obj.css('opacity', 1).css('filter', 'alpha(opacity=100)');
obj.css('background', '#9dc0f4');
// add appropiate action buttons
$('button.pageButton').css('display', 'inline');
}
function addPage() {
window.location = "index.php?rt=cms/editPage";
}
function delPage(page) {
var confirm = window.confirm("Are you sure? Any sub-pages WILL BE deleted also.");
if (confirm) {
var url = './components/cms/controller/forms/deletePage.php';
$.ajax( {
url : url,
type : 'GET',
data : 'id=' + page,
success : function(result) {
if (!result) {
document.location = "index.php?rt=cms";
} else {
window.alert('There was a problem deleting the page');
}
}
});
}
}
function editPage(page) {
var url = "index.php?rt=cms/editPage/" + page;
window.location = url;
}
Is it possible that you are linking to (some of) the script files using a src that points to a file on your local disk/HDD? If so, that would explain why it works only on your machine, as then only your machine has access to the script file.
Thank you one and all for your suggestions. The end problem was miscommunication. I work from home, and upload my projects to a SVN server, which the boss then uses to update the live server. Somehow, the correct files were not getting updated - a communication error on my part. Another possible reason was that the page, while being declared XHTML 1.0 Strict, had something like 50 validation errors (mosting incorrectly nested UL), and I cleaned that up to 5 errors. So thank you all, but again a sad example of the importance of team work communication.

Categories

Resources