impress / impress.js

It's a presentation framework based on the power of CSS3 transforms and transitions in modern browsers and inspired by the idea behind prezi.com.
http://impress.js.org
MIT License
37.62k stars 6.67k forks source link

Add custom class names of steps to body element #564

Closed Nekomajin42 closed 8 years ago

Nekomajin42 commented 8 years ago

Hey guys!

I created a presentation similar to a mind map a few days ago. When I reached the end of my presentation, I wanted to show an overview of the mind map, so I scaled out, and thanks to the impress-on-"ID" class, I was able to set the opacity of every step to 1.

Then I had an other idea. My map had many subtrees, so to make it easier to follow, I wanted to change the background color of the whole page, when I enter a new subtree. But if I apply a unique ID to every step, the CSS will be a mess.

So I implemented a few lines of code, which fetches the custom class names of the active step (excluding: step, active, past, present, future), and appends an impress-in-"className" class to the body for each of them. Here is the code:

// remove classes of the previous step
for ( var i=0; i<body.classList.length; i++ )
{
    if ( body.classList.item(i).match(/^impress-in-/) )
    {
        body.classList.remove( body.classList.item(i) );
    }
}
// append classes of the current step
for ( var i=0; i<el.classList.length; i++ )
{
    if ( el.classList.item(i) !== "step" && el.classList.item(i) !== "active" && el.classList.item(i) !== "past" && el.classList.item(i) !== "present" && el.classList.item(i) !== "future" )
    {
        body.classList.add( "impress-in-" + el.classList.item(i) );
    }
}

With this piece of code (in the "goto" function), I can easily apply different styles to the whole canvas, depending on the range of steps I am currently in.

What do you think? Should I create a pull request, or you want to discuss it further?

FagnerMartinsBrack commented 8 years ago

So just to make it clear: You want to change the whole background of the body once the presentation enters a step, and since CSS doesn't support backwards matching you want to add a class in the body element, is that it?

Did you know that impress.js already have that functionality in the form of .impress-on-step-x?

See the image below, more specifically in the console at the bottom:

example impress

Does that work for your use case?

FagnerMartinsBrack commented 8 years ago

Neverthless I have added a bullet point here to document the functionality in the reference API that we are building (although this is sort of mentioned in the annotated index.html file).

Nekomajin42 commented 8 years ago

The answer to your first question is yes.

As I've written, the impress-on-"ID" class works fine when I want to catch one step. But I want to apply some style (background, font color, anything) when I am in a range of steps. Then I want to apply other styles when I am in an other range of steps.

With the impress-on-"ID" class, I have to write long and complex selectors in the CSS, so the code will be hard to maintain. And I can't just apply the styles when I enter a desired step, then apply other styles a few steps later, because it also has to work when I am walking backwards in the presentation.

The code I've written in my first comment works. It is tested. But maybe it is not the most effective way to do this, so I'd like to discuss it.

FagnerMartinsBrack commented 8 years ago

Ok, I guess I got it now from this part:

... fetches the custom class names of the active step (excluding: step, active, past, present, future), and appends an impress-in-"className" class to the body for each of them.

So, you get all class names of each step and append to the body? Why would that be different from using .impress-on-ID for each style declaration?

I don't see the value in adding a different behavior for something that can be achieved right now using the current functionality. It seems this use case of not wanting to repeat style declaration is more suited for a CSS preprocessor such as SASS, LESS or similar, where you have things like loops and variables that you don't have in plain CSS, not something that should be handled in the low-level presentation tool itself.

Nekomajin42 commented 8 years ago

Come on, really?

And I can't just apply the styles when I enter a desired step, then apply other styles a few steps later, because it also has to work when I am walking backwards in the presentation.

I don't get all class names. The built-in names are excluded. There won't be (for example) an .impress-on-active class.

FagnerMartinsBrack commented 8 years ago

I don't get all class names. The built-in names are excluded. There won't be (for example) an .impress-on-active class.

I get that, when I meant "all" classes I meant "all classes that were not added by impress.js".

And I can't just apply the styles when I enter a desired step, then apply other styles a few steps later, because it also has to work when I am walking backwards in the presentation.

Can you please elaborate on this part? Why can't you just apply the styles when entering a desired step? What do you mean by having to work when it is walking backards the presentation? Can you provide some code sample that shows the problem and workarounds, preferentially on jsfiddle or jsbin?

Thanks.

Nekomajin42 commented 8 years ago

https://jsfiddle.net/Nekomajin42/jf8wLaw1/

It does not work in the preview, but it works in my local machine.

So, how it works. There are 9 steps in this presentation. I want to change the background color or the whole presentation (body element) when I enter the first step in a range. For example, I start with a blue background, and I use it, until I enter step 4, where I change the background to red. It will be red until I enter step 7, where I change it to green.

Until now, the .impress-on-id class works. I give ID-s to step 1, step 4 and step 7, and it's fine.

But then I start to go backwards in the presentation. From step 9 to step 8, then step 7. Still with a green background. And I enter step 6 (which has a .red class) where I change the background from green to red.

Now I have to give ID-s to step 9, step 6 and step 3 too. But if I use classes (as I did in the fiddle), the whole stuff is easier.

And imagine if I want to mix different ranges! I want to go through a few blues, then a few greens, then reds, and greens again...

This feature is usefull. The only questions is the implementation. I get it, there can be many .impress-in- classes appended to the body, so maybe a data- attribute would be better, I don't know. It is up to discuss.

FagnerMartinsBrack commented 8 years ago

I managed to make the failing example work in jsbin: http://jsbin.com/tisikasuge/1/edit?html,css,js,output. It seems jsfiddle does not allow the presentation to start, don't know why.

Here is the example working using impress.js API: http://jsbin.com/meducilaze/1/edit?html,css,js,output

Here is the example using scss: http://jsbin.com/mifinilasa/1/edit?html,css,js,output.

But then I start to go backwards in the presentation. From step 9 to step 8, then step 7. Still with a green background. And I enter step 6 (which has a .red class) where I change the background from green to red.

Isn't that expected? If you go backwards the color stay the same, but if you change to a different step, the color also changes.

Now I have to give ID-s to step 9, step 6 and step 3 too.

Why do you need to give IDs to step 9, step 6 and step 3?

And imagine if I want to mix different ranges! I want to go through a few blues, then a few greens, then reds, and greens again...

Can you share a use case for that?

Just to explain why I am asking so many questions:

The goal of impress.js is not to handle specific use cases, but serve as a framework that allows presentation to be built on top of its API. By prioritizing features that make the development easier for a specific paradigm or style (pure CSS, for example), we are increasing the complexity of impress.js and also increasing the amount of features that we need to support. As you can see, impress.js have very weak tests, and we are working to make this better so that we can land more important features that are being requested over and over again. If something can be solved outside impress.js, that is the recommended approach, unless it is something whose tradeoff is unnacceptable.

That said, I need to understand perfectly the use case, so that we can find something that might be blocking you from using the framework on its current state.

Thanks.

Nekomajin42 commented 8 years ago

Would you create a presentation with dozens of steps with either of the methods you've linked? Because I would not. I like to keep my code clean. With my solution, I only have to insert/rearrange/edit/delete the steps in the HTML. With your solutions, you have to modify the CSS too.

I don't think I have to prove with any more usecases. A framework has to cover as much usecases as possible with built-in solutions. This framework can handle only one step (with the .impress-on- class), and can not handle ranges of steps, which is a big deficiency. If you want to build a professional software, you can not rely on third-party technologies like CSS preprocessors.

I provided clear usecases. I shared my code. Use it if you want.

FagnerMartinsBrack commented 8 years ago

I don't think I have to prove with any more usecases.

There is nothing to prove. In order to consider any new feature, we need to understand what the use case is, so that we can weight the tradeoffs in supporting it or not.

A framework has to cover as much usecases as possible with built-in solutions.

I don't know which framework are you refering to, the purpose of impress.js is not to act as a silver bullet for all use cases, but to focus in the most common ones. Understanding the use case will make it possible to be identified as a recurrent request or not.

If you want to build a professional software, you can not rely on third-party technologies like CSS preprocessors.

CSS preprocessors are totally acceptable for building professional software, because they fix deficiencies that CSS have and help in use cases that would otherwise not be possible with plain CSS (like loops, variables, mixins, functions, etc.). If one don't want to use them, that is a personal choice, in the current state of impress.js we don't have enough resources to handle things that can be successfully achieved using other means such as a CSS preprocessor (I don't know if this is the case, that's why we need to understand the applicability).

Nekomajin42 commented 8 years ago

Man, I clearly stated in my first comment, that using the .impress-on- class to handle several ranges of steps results a messy code. Both HTML and CSS. Then you showed me two examples with messy code.

I tried a few visual editors to build a presentation with impress, but all of them is incomplete and messy, because the framework itself does not provide the necessary tools. I shared a very simple solution to an existing problem, but you are trying to convince me that my problem does not valid.

You know what? Just create a presentation with hundreds of steps! Use your solution, then use my solution, and if you still don't understand what I am talking about, just close this issue!

FagnerMartinsBrack commented 8 years ago

... and if you still don't understand what I am talking about, just close this issue!

Ok, thanks for opening the issue. If you want to continue the discussion, please comment here mentioning one of the members.