Simplify a jQuery function for multiple elements - abstraction

I'm working on my new portfolio and I have a list of projects which are using show and hide functions. In my case, I'wrote the code for each project, but is it very repetitive. So I would like to know if there's a technique to write the same function for each project.
Here is my jquery code:
$project1.hide();
$("a.show_hide_project1").show();
$('a.show_hide_project1').click(function() {
$project1.delay(100).slideToggle("slow");
$project2.hide(); $project3.hide(); $project4.hide(); $project5.hide();
$project6.hide(); $project7.hide(); $project8.hide(); $project9.hide();
$project10.hide();$project11.hide(); $project12.hide();
});
$('a.next1').click(function() {
$project2.fadeToggle("slow");
$project1.delay(600).hide();
});
$project2.hide();
$("a.show_hide_project2").show();
$('a.show_hide_project2').click(function() {
$project2.delay(100).slideFadeToggle("slow");
$project1.hide(); $project3.hide(); $project4.hide(); $project5.hide();
$project6.hide(); $project7.hide(); $project8.hide(); $project9.hide();
$project10.hide();$project11.hide(); $project12.hide();
});
$('a.next2').click(function() {
$project3.fadeToggle("slow");
$project2.hide();
});
$('a.previous2').click(function(){
$project1.fadeToggle();
$project2.hide();
});
$project3.hide();
$("a.show_hide_project3").show();
$('a.show_hide_project3').click(function() {
$project3.delay(100).slideFadeToggle("slow");
$project2.hide(); $project1.hide(); $project4.hide(); $project5.hide();
$project6.hide(); $project7.hide(); $project8.hide(); $project9.hide();
$project10.hide();$project11.hide(); $project12.hide();
});
$('a.next3').click(function(){
$project4.fadeToggle("slow");
$project3.hide();
});
$('a.previous3').click(function() {
$project2.fadeToggle();
$project3.hide();
});
Any help will be very appreciated.
Thanks in advance.

Here's a quick stab at it: http://jsfiddle.net/Jj2Q7/1/
The animations are not exactly as you have it, and I doubt if that's the most efficient way to do it, but hopefully it'll serve as a starting point.
Update
Here's another version which makes liberal use of data attributes: http://jsfiddle.net/Jj2Q7/3/
It should be faster than the previous, but relies on the HTML tags having the right attributes set.

First off, you should probably be leveraging a common css class to select all of them
$('.projectItem').click(function () {
$('.projectItem').hide(); //hide them all
$(this).delay(100).slideFadeToggle("slow"); //then show the one being clicked.
});
Where your Html would look more like this.
<div class="projectItem" id="project1"/>
<div class="projectItem" id="project2"/>
<div class="projectItem" id="project3"/>
<div class="projectItem" id="project4"/>
Just a really rough idea.

Basically you need to give your HTML a sort of class that makes it identifiable as a "project" , and add some rel or data attribute to the individual projects
Your code then translates to something like this: (depending on your HTML , may vary)
$(function(){
$(".project").hide();
$("a.show_hide_project").show();
$('a.show_hide_project').click(function(){
$(".project").hide();
$(".project[rel="+$(this).attr('rel')+"]").delay(100).slideFadeToggle("slow");
});
});

Related

How to put a reactive Template inside of a Surface in famo.us/Meteor

I've read several posts on this but nothing that would really answer my question in an up-to-date way (i.e. UI.insert is depreciated).
So what's the best way of inserting/rendering a Template into a Surface reactively, meaning, not only one data object (renderWithData), but whatever is defined in the Template.helpers should also be updated reactively. Code tried so far:
var div = document.createElement('div');
//UI.insert(UI.render(function() { return Template.hello; }), div);
surface = new famous.core.Surface({
//content: Blaze.toHTML(function() { return Template.hello; }),
//content: div,
content: '<div class="hell"></div>',
size: [window.innerWidth, window.innerHeight],
properties: {...}
});
Blaze.render(function() { return Template.hello}, $('.hell')[0]);
These are 3 different approaches I've tried. First UI.insert inserts it, but handlebars-style Helpers are not recognized. Second, toHTML, no reactivity, even when I put everything into a Tracker.autorun(). Third, Blaze.render(...), doesn't work at all.
Is there an easy solution to this?
one possible answer is to use Famodev
var ReactiveTemplate = famodev.ReactiveTemplate;
var reactive = new ReactiveTemplate({
template: Template.mytemplate,
data: Collection.find().fetch(),
properties: {
}
});
Maybe it will be useful in some way http://github.com/dcsan/moflow

jQuery UI .sortable and iFrames

I have a serious issue with .sortable and all the iframe texteditors out there.
I have the following example code:
html:
<div id="content" style="height: 400px;">
<div><textarea></textarea></div>
<div><textarea></textarea></div>
</div>
script:
$("#content").sortable();
This makes the two textareas draggable. No problems till here... Now lets add the wysiwyg editors...(I tried many of them ckeditor, tinyedit, tinymce, elrte, and so on)
As an example lets do it with tinyMCE:
function ini(){
tinymce.init({
menubar : false,
toolbar1: "bold | link",
selector: "textarea",
});
Ok so this is where the problems are rising. If I know drag and drop the one textarea just a little bit, the editor field is going to disable itself.
What did I try until this moment:
- I added start and stop events to the sortable method, but without success.
- I tried the frameFix: true also without any differences in behaviour.
Anyone with some hints or solutions?
Thx
Cervisias
I figured out a solution. Its a total workaround but it works :)
So basically what I am doing is to save the content of every texteditorfield into an array and putting it back to the editor after the use of the sortable method.
so it looks like:
$("#content").sortable({
start: function(){
newEditors = new Array();
for(i=0; i < $("textarea").length; i++){
var content = tinyMCE.get(tinyMCE.editors[i].id).getContent();
var id = tinyMCE.editors[i].id;
newEditors[i] = {"id":id, "content":content};
}
tinyMCE.remove(); //as a fix for FF
},
stop: function(){
ini(); //re-initiate the tinymce again (if you don't do that, the field wont be editable)
for(var nr in newEditors){
tinyMCE.get(newEditors[nr].id).setContent(newEditors[nr].content);
}
}
});
So if sb has the same problem and figures out an other way to solve it, would be nice to see those solutions too.
Thx
Cervisias

CSS3: set background image to rel attribute value

I'm looking to set the background-image (or even render an image via the pseudo elements :after or :before) to the value, which will be a URL, of a rel attribute, but only in certain cases (this is a cloud file listing). For example:
HTML:
<div class="icon ${fileExtension}" rel="${fileURL}"></div>
It would be great if I could do something like this:
CSS:
.icon.png,
.icon.jpg,
.icon.jpeg,
.icon.bmp,
.icon.gif { background-image: attr(rel,url); }
... but obviously that doesn't work as, if I'm not mistaken, the attr() CSS function only works inside pseudo element blocks.
I know there are ways of doing this using conditional JSP or even jQuery logic, but I'd like to figure out a neat way of doing it via CSS3, since I'm only concerned with modern browsers at the moment anyway.
Also, I don't want to explicitly set the background image to the URL or create an <img> element, because by default if the file is not a supported image, I'd rather display a predetermined set of icons.
Using
.icon:after{ content: ""attr(rel)""; }
displays the rel value as text.
A jQuery solution is to add the background-image (taken from the rel value) as inline CSS:
jQuery(function($) {
$('.icon').each(function() {
var $this = $(this);
$this.css('background-image', 'url(' + $this.attr('rel') + ')');
});
});
I've tried to do something using jQuery but i don't exactly understand what you want so i can't go on with my code. So far i've done only this.
EDITED I hope it's exactly what you need
$(function(){
var terms = new Array('png','jpg','jpeg','bmp','gif');
$('.icon').each(function(){
var t = $(this),
rel = t.attr('rel'),
cls = t.attr('class');
cls = cls.split(' ');
for (var i=0; i < terms.length; i++) {
if (terms[i] == cls[1]) {
t.css('background-image','url('+rel+')');
}
}
});
});
if you can give me a better example, to undestand exactly what you want, i hope somebody from here will be able to solve your problem.
Regards,
Stefan
I've decided to go the jQuery route, and used a combination of #ryanve and #stefanz answers. Thanks guys
$(document).ready(function() {
$(".png,.jpg,.jpeg,.bmp,.gif,.tiff").each(function(n) {
var bg = 'url(' + $(this).attr("rel") + ')';
$(this).css('background-image', bg);
});
});
I think this is relatively neat/concise and works well for my needs. Feel free to comment on efficiency, methodology, etc.

CSS ie6 hover issue

I am pretty sure everyone knows the hover issue in IE6.
I tried to fix the problem by using "csshoverfix.htc" or "whatever:hover". I downloaded it from the writer's page, and ofcourse I added
body { behavior:url("csshover.htc"); }
to my css file, But it didnt help.
I also tried to use jquery hover function:
$(document).ready(function(){
$('#autoSuggestionsList li').hover(
function(){
alert("test");
},
function(){
alert("test");
})
});
But also it didnt work.
I dont know if it can be the reason why it doesnt work, but the <li> with the hover, are made in real time (ajax).
anyway, how can I fix the hover issue?
Thank you.
I dont know if it can be the reason why it doesnt work, but the <li> with the hover, are made in real time (ajax).
Possibly. Try using .live() instead so that it works with elements that come from Ajax responses:
$(document).ready(function() {
$('#autoSuggestionsList li').live(
{
mouseover: function() {
alert("test");
},
mouseout: function() {
alert("test");
}
});
});

IE select issue with hover

A friend and myself are trying to workaround IE (7/8). We have built a canonical example here:
http://www.mathgladiator.com/share/ie-select-bug-hover-css-menus.htm
Using a CSS menu, we would like to have selects in them. However, in IE, the menu goes away when you interact with the select box. We believe this has to do with a bug in how selects affect events.
Is there a workaround? At least with pure CSS or DOM hacks?
I do not think there is a pure CSS way around this. This is due to a very common bug to the way IE handles events on select elements.
You can however work around it with Javascript:
<script type="text/javascript">
$(document).ready(function () {
$('.nav_element a').mouseover(function() {
$('.submenu').hide();
$(this).parent().find('.submenu').show();
});
$('.submenu').mouseover(function() {
$(this).show();
});
$('.submenu').mouseout(function (e) {
// Do not close if going over to a select element
if (e.target.tagName.toLowerCase() == 'select') return;
$(this).hide();
});
});
</script>
The code above uses jQuery.
Here is a way to improver select behavior in IE7/8, but it does not fix the issue
Change DOCTYPE
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Add script
<script>
function ddlOut(e) {
setTimeout(function() { e.className = e.className.replace(' over', ''); }, 1000)
}
</script>
Add css
#nav .over div.submenu
{
display: block;
}
#nav .nav_element{
behavior: expression(
this.onmouseover = new Function("this.className += ' over'"),
this.onmouseout = new Function("ddlOut(this)"),
this.style.behavior = null
);
}
It will work better at least but of course not perfect.
My advice is to change select control to html equivalent. I use OboutDropDown that has a nice view. There are many implementations that can suite you needs.
First you need to expand the :hover surface underneath your menu.
So in your css add width:310px;height:220px to #nav .nav_element a.
(also add a class or an id on the second div styled with top:220px)
Now you just need to simulate a mousedown triggered when you click on the select which will halt when the selection between the options is done - you can probably do the last part if you check for the onfocus state of the select which will stop the mousedown.

Resources