I'm pretty new to javascript/jquery and I just built a simple slide menu.
It has 3 menus and each menu has a submenu...everything is working fine, I just want to know if there's a better way to accomplish the same task.
Here's my js code:
function menuOpen(menu){
if(menu=='menu1'){
$("#sub2").slideUp(400);
$("#sub3").slideUp(400);
$("#sub1").slideToggle(400);
}else if(menu=='menu2'){
$("#sub1").slideUp(400);
$("#sub3").slideUp(400);
$("#sub2").slideToggle(400);
}else if(menu=='menu3'){
$("#sub1").slideUp(400);
$("#sub2").slideUp(400);
$("#sub3").slideToggle(300);
}
}
without seeing your HTML:
LIVE DEMO
function menuOpen(menu){
var num = menu.match( /\d+/ ); // Regex expression to retrieve the Number
$('[id^=sub]').slideUp(); // slide UP all ID starting with sub
$('#sub'+num).slideToggle(); // get the desired ID :)
}
Use of jQuery means that we want to easily manipulate DOM elements , which means that without seeing a HTML sample of your DOM nodes and structure you're about to target it's hard to make the above even simpler.
Related
First of all a disclaimer, I'm not a dev. I'm halfway through The Odin Project and have covered some HTML and CSS, but, have not yet started on JS. In order to help with my learning I've created my own blog. My aim is for each blog post to have its own stylesheet (so with each new post I learn a little more about CSS).
Anyway, I plan to write a post about the benefits of using an eReader, specifically the Kindle. I've styled the page to look like a Kindle Oasis, and I'd like the reader to be able to step through the article contents via the Kindle's next/prev buttons, but, as I'm not a dev, this is where I'm stuck. Via Stack overflow I've managed to add some JS that will display page 1, 2 and 3 via dedicated buttons for each dive element, but, what I really need is to step through x number of pages via the prev/next buttons.
Here's what I have so far: https://codepen.io/dbssticky/pen/yLVoORO. Any help would be much appreciated. What I should do of course is finish The Odin Project and come up with a solution on my own, but, I'd really like to get this Kindle article published sooner rather than later. Hence my rather cheeky request for assistance.
Here's the JS I'm currently using:
function swapContent(id) {
const main = document.getElementById("main_place");
const div = document.getElementById(id);
const clone = div.cloneNode(true);
while (main.firstChild) main.firstChild.remove();
main.appendChild(clone);
}
You have the right idea and it just needs a few adjustments to get the previous/next functionality.
Currently your div IDs are following the format operation1, operation2, and so on. Since you want the previous/next functionality you'll need to change your 'swapping' function, which currently takes the full ID, to use the numeric portion only.
Add a new function which appends the number to 'operation' instead of using the whole thing:
function goToPage(pageNumber){
const main = document.getElementById("main_place");
const div = document.getElementById("operation" + pageNumber);
const clone = div.cloneNode(true);
while (main.firstChild) main.firstChild.remove();
main.appendChild(clone);
}
And then change your Page 1/2/3 buttons to use goToPage(1), goToPage(2) and so on.
Now for the previous/next functionality you'll need a way to track which page you're on, so that you can figure out which page to load.
Add a variable at the top (outside functions)
var currentPage = 0;
Then add a line in your goToPage function to track the page you're on.
currentPage = pageNumber;
Now that you're tracking you can add a previous and next function.
function goNextPage(){
goToPage(currentPage-1);
}
function goPreviousPage(){
goToPage(currentPage+1);
}
Then call it from the previous and next buttons.
<button onClick="goNextPage()" class="next-button"></button>
<button onClick="goPreviousPage()" class="previous-button"></button>
Here's a codepen: https://codepen.io/srirachapen/pen/WNZOXQZ
It's barebones and you may have to handle things like non existent div IDs.
HTML
<button class="next-button" onclick="nextContent()"></button>
<button class="previous-button" onclick="prevContent()"></button>
JS
var pageid = 0;
var maxpage = 3;
function nextContent() {
if(pageid == maxpage) return
pageid++
swapContent(`operation${pageid}`)
}
function prevContent() {
if(pageid == 1) return
pageid--
swapContent(`operation${pageid}`)
}
you can try this to switch between pages. But you may need to edit the "swapContent" method more sensibly.
Track the Current Page
Whatever solution you use to render pages & links (manual hardcoded links & content vs externally-stored & auto-generated), one thing is unavoidable: You need to track the current page!
var currentPage = 0
Then, any time there's a page change event, you update that variable.
With the current page being tracked, you can now perform operations relative to it (e.g. +1 or -1)
I'd suggest making a goToPage(page) function that does high-level paging logic, and keep your swapContent() function specifically for the literal act of swapping div content. In the future, you may find you'd want to use swapContent() for non-page content, like showing a "Welcome" or "Help" screen.
Example:
function goToPage(page) {
// Update `currentPage`
currentPage = page
// ... other logic, like a tracking event or anything else you want you occur when pages change
// Do the actual content swap, which could be your existing swapContent()
swapContent('operation'+page)
}
You'd invoke the function like so:
goToPage(3) // Jump to a specific page
goToPage(currentPage + 1) // Go to the next page
goToPage(currentPage - 1) // Go to the prev page
You can make separate helper functions like "goToNextPage()" if you desire, but for sure you start with a fundamental page-change function first.
I just need some advice and help. I have 7 different divs and every div should do something else when clicking on it (owl carrousel).
Now i just have everything "hard coded" but that is not very efficiƫnt
Example:
when i click div 1: $(".div1").css('-webkit-filter','blur(5px)');
when i click div 2: $(".div2").css('-webkit-filter','grayscale(100%');
etc.
Do i need to keep "hard coded" or is there a better solution for my question?.
I am a real newbie.
Thanks in advance
Try doing something like:
/* Array of effects */
var effectArray = ['blur(5px)', 'grayscale("100%")'];
$(".divClass").click(function () {
// Wrap the clicked item in jQuery.
// .index() get its index 0 to "n".
$(this).css('-webkit-filter', effectArray[$(this).index()]);
});
EDIT i forgot to wrap the divclass in jQuery. you can obviously do this without jQuery too
Also just realized you want it on click.
I'm trying to find a way to get the ids from dragged divs after they are in the drop zone.
All the drag components have an id from drag1 - drag8 and the drop zone is div drop zone. Because there are no divs in the drop zone when the page loads I want to gather the ids on a save button for now with a text box entry and drop down menu select.
I have tried the code below:
$(document).ready(function() {
$("#dropzone div").click(function() {
var index = $("#dropzone div").index(this);
$("#dropzone_drag").html("Index " + drag + " was clicked");
});
});
And I use jQuery for the text box, which works nicely:
$(document).ready(function() {
$('#save').click(function() {
alert($('#name').val());
});
});
How do I find the ids from dragged divs after they are in the drop zone?
After playing around i came up with the following:
var ids = {};
$("#dropzone>div").each(function(i){
ids[i] = $(this).prop('id');
});
which at the moment says undefined, but i did manage to put it on the save button so it no longer pops up when i open the page.
Any suggests please?
In my comprehension .index(this) returns the index of the element relative to the list "#dropzone div"., which may or may not contain the elements in the order you want. But if all your elements have a common class, say ".foo_bar" it probably would be easier to know the id given an clicked element.
Otherwise, as you're using this on the function, if this is one of your "drags" it is probably easier to pick the id from this than to try the indexes.
Try doing it like that and maybe it'll word better.
ids = {};
$("#dropzone>div").each(function(){
ids[$(this).prop('id')] = $(this).prop('id').replace(/[^0-9]/g, '');
});
the code .replace() means that we are removing characters (in this case anything that isn't a number) from the string so we end up with it's true number. Instead of it's place in the DOM.
If i didn't comprehend well your problem, correct my comprehension errors and i will edit the answer. And an html of the zones would be nice ;)
The following code worked for me:
<script>
var div = document.getElementById('dropzone')
</script>
and on the button i added:
alert( div.innerHTML )
The result gave me all of the div information from it's html page so i could select the information i wanted to push to the database.
Thank you all for you input and advice.
Matthew
I've a small webapplication that works with some drag / drop functionality. Just imagine a small order system in which you can say order 1 (draggable) will be done by employee 2 (droppable). That works fine. BUT:
Every 20sec. I ask the database via AJAX for new orders. These new orders will also be draggable. In case that another college has given an order to en employee the list of orders for every employee is also no loaded. To enable drag / drop after the ajax request I had to run:
$('.order').draggable({
..
});
and
$('.employee').dropable({
..
});
So the jquery function walks every 20 secunds through the hole DOM. After 10-15 minitues the app becomes very slow. Do you have an idea how to ingrease that process? Is it possible to give an absolute statement that every .order class is draggable even if this element will be create after the first registration?
I think the problem is that the elements that are already on the page become draggable over and over again.
I think a solution would be to assign a class to those that already have it:
$('.order').each(function() {
var element = $(this);
if ( !element.hasClass('event-already-attached')) {
element.addClass('event-already-attached').draggable({
})
}
});
Thanks # Jonas your great idea did it!
You can use the classes ui-droppable and ui-draggable for that job
$('.order').each(function() {
var element = $(this);
if ( !element.hasClass('ui-droppable')) {
element.droppable({
...
}
});
I am working on a listview which has auto dividers based on date it is a very long list & data-autodividers='true' works fine but I want to further improve it by making the listview collapsible on date.
This can be done from back-end using c# (I am working on an asp.net webform mobile website) where I group my list based on Month-Year and make each group collapsible.
But I would love to do it with jQuery as I do for autodivider. I have set up same on jsFiddle.
http://jsfiddle.net/5PnBT/10/
How can I make these auto-divider collapsible using jQuery without doing it from code-behind file (c#)?
I did not see where jquerymobile has this as a build in option.
$(document).on("pageinit", "#page-wrapper", function () {
$("#hp-latest-articles").listview({
autodividers: true,
autodividersSelector: function (li) {
var out = li.attr('date');
return out;
}
}).listview('refresh');
});
If I have understood your problem, I think you just have to use the $.mobile.listview.prototype.options.autodividersSelector option. I had a similar problem, so if you need to list them according to the date attribute on the single element, do:
$( document ).on( "mobileinit", function() {
$.mobile.listview.prototype.options.autodividersSelector = function( element ) {
return (element.attr('date'))
};
});
I prepared a jsbin for that: http://jsbin.com/enuwoj/1/edit
There are two solutions to your problem.
Either you use the collapsible list sets on the jQuery Mobile side, then you will be able to reach exactly what you are looking for. You might nee to edit the looks of the element using CSS to make it look like a listview.
http://jsfiddle.net/rc9Gk/
<div data-role="collapsible">
<h3>Title</h3>
<ul><li>Item1</li><li>Item2</li></ul>
</div>
Second solution would be to apply custom event handlers on click event of the listview control. Whenever a click event occurs on a list divider you can hide the following list elements till the next auto-divider. This solution needs a bit of coding. If this solution fits you, I can write that code for you do let me know.
I believe your problem is solved by adding the following to the bottom of your original fiddle
$('.ui-li-divider').click( function(ev ){
var li = $(ev.target).next(':not(.ui-li-divider)');
while ( li.length > 0 ) {
li.toggle();
li = li.next(':not(.ui-li-divider)');
}
});
Here is the updated jsFiddle
Basically, everytime you click a divider, it looks for all following LIs until the next divider and toggles their visibility.
You'll need either <div data-role="collapsible"> or <div data-role="collapsible-set">, depending on if you wanted to group them or not.
If you want them pre-collapsed by default, include the data-collapsed="true" attribute as well.