Posts tagged with 'Wednesday CODE'
Oct
4
1 years ago

Wednesday CODE: Trello Remake, part 2, drag'n'drop

0 comments

Continuing our series, we will now essentially write TIScipt code to make our Trello board interactive with drag'n'drop support! If you missed part 1, check it here.

Download source-code

Test DEMO with this link: (how to run it)

Drag-me to OmniFiddler and Run


Drag'n'drop in Sciter

Well, it's easier to make than to explain. I won't dive too deep in the implementation, instead, better to explain the logic behind it so you might be able to tweak and even reuse my drag'n'drop implementation.

I decided to code drag'n'drop from scratch. Sciter's SDK samples has a drag'n'drop library which you may want to resort as a more flexible and reusable approach. Check it at sciter-sdk-3/samples/drag-n-drop-manager/.

However, our Trello board drag'n'drop has so specific requirements that probably that library would not suffice or would make it a harder implementation. I recommend you to check ddm.tis/ddm2.tis and the samples as an option to your drag'n'drop scenario.

Check Trello2.html where is our final HTML code, here at GitHub.

And drag-n-drop.tis where I put the main script code, here at GitHub.

TIScript explained: element script prototype

Before I talk about drag'n'drop, you must understand Sciter's protoype mechanism that our demo uses to link script behavior to our HTML structure (also, you get a sense of development practices right out of the box).

Note that drag-n-drop.tis contains two behaviors: DndListBehavior handles drag'n'drop between lists (columns), and DndCardBehavior handles drag'n'drop between cards (tasks).

Well, behaviors are just a more organized way to set the code/logic-layer behind an element because you are declaring in CSS what element gets attached to what behavior, so you have all CSS cascading/priority rules applying.

Docs about behavios are here.

In CSS there are 3 mechanism that you can use to relate/attach a behavior to an element:

  • aspect: call a TIScript function with element set to 'this'
  • prototype: instantiate and attachs a TIScript class to the element
  • behavior: instantiate and attachs a native (C#, C++, Python, ..) behavior to the element

So yes, you can have a native behavior when you need the logic to be in the native side.

In our demo I am only using the prototype mechanism, see lines 81 and 140.

TIScript explained: drag'n'drop algorithm

For creating any kind of drag'n'drop support in Sciter, you will essentially resort to a standard sequence of handling user events and mouse capture. What is mouse capture?

When an object captures the mouse, all mouse related events are treated as if the object with mouse capture perform the event, even if the mouse pointer is over another object.

Simply put: when you capture the mouse, the element capturing it will receive all mouse events, even if cursor is outside the element box/area or even the application window. This is very usefull for drag'n'drop.

The basic sequence for any custom drag'n'drop implementation in Sciter is:

  • Event.MOUSE_DRAG_REQUEST
  • this.capture(#strict) and captured = true
  • Event.MOUSE_MOVE if captured==true
  • Event.MOUSE_UP if captured==true
  • this.capture(false) and captured = false

I'll explain each step and point the corresponding line of code:

  • Event.MOUSE_DRAG_REQUEST line 57: logic to detect when to start a drag'n'drop operation; this event happens when user clicks and holds mouse hover our element, and move it a little bit (which does not happens in a simple click event)

  • this.capture(#strict) line 69 and captured = true line 70: to start our drag'n'drop, we capture the mouse making all mouse messages/events to be delivered to 'this' element; also we need to set a global variable so we know that a drag'n'drop is in progress and we should handle MOUSE_MOVE events

  • Event.MOUSE_MOVE if captured==true line 25: here we put all the logic of what happens while the object is beeing dragged

  • Event.MOUSE_UP if captured==true line 19 here we put all the logic of what happens when user releases the mouse button / drops the object

  • captured = false line 21 and this.capture(false) line 23: with our drag'n'drop operation finished, we must manually release mouse capture (else mouse interaction behaves very oddly) and unset our global variable

Next time

Our next installment is exciting. I'll cover Sciter C# native implementation. Stay tunned.

Sep
21
1 years ago

Wednesday CODE: Trello Remake, part 1

0 comments

Trello is a kanban-like task management tool, the one which I personally use. In this Wednesday CODE installment we will be remaking its UI.

I won't be making another TODO list system, the world is already full of then.

Instead, I will focus on what I think are the most clever UI details of this tool. To me, it is distinctive because of the minimalist layout, and how you can nicely drag'n'drop the tasks between the columns. If you want then, you might easily extend it to add a complete TODO list support.

The main goal is to achieve a functional UI with drag'n'drop where you can rearrange the columns, and also the tasks inside each column. So it is all about frontend implementation in Sciter. I will divide it in 2 posts:

  1. This one deals with implementing every visual aspect required, that is, we will write all HTML and CSS code necessary, and any script required to dynamically construct HTML.
  2. In the second part we make the UI interactive by adding the drag'n'drop support through scripting.

Download source-code / GitHub

Test DEMO with this link: (how to run it)

Drag-me to OmniFiddler and Run


HTML explained: templates

The file Trello.html contains all our HTML code, you should check it at GitHub.

Our Trello board has lists (columns) and cards/tasks (itens inside each column). Lists are arranged horizontally, cards vertically.

In the HTML approach I am using, I declare two HTML 'templates', #tpl-list and #tpl-card, one for each of these kind of item. I use this HTML template as the basis to create every new list/card in order to populate the page with lists and cards:

<div #tpl-list style="display: none">
	<section>
		<div .list-header>
			<span />
			<i .ft.ft-dot-3 .dark-hover />
		</div>

		<ul />

		<div .list-newcard.dark-hover>Add a card...</div>
	</section>
</div>

<div #tpl-card style="display: none">
	<li>
		<div .content>
			<img .card-cover />
			<div .card-labels />
			<div .card-title />
			<div .badges />
		</div>
		<div .card-edit>
			<i .ft.ft-pencil.dark-hover />
		</div>
	</li>
</div>

The parent div is hidden so our template does not appears. What really matters is the child section/li element which is actually our template, which we will clone() in script in order to create every new item. I'll cover the code behind below.

HTML explained: HTML/CSS subtleties

Sciter's HTML/CSS support has some subtleties which are not supported by standard browsers. It is standard HTML, until you notice some subtleties. Notice how we declared the <button> element:

<button #btn-add-list.std-btn>

Instead of declaring the element ID with an id="btn-add-list" attribute, as in <button id="btn-add-list" />, we can simply say #btn-add-list, as you would write an ID selector in CSS.

You can do the same for the class attribute, so <button class="btn btn-colored" /> can be written as <button .btn.btn-colored />. Pretty clever method for writing the ID or classes of an element by using the same syntax from CSS.

Sciter supports more HTML shortcuts, see here.

CSS explained: 'flow' layout

Besides basic CSS code for making our Trello UI, for achieving our Trello drag'n'drop goal, we must set a proper flow to our layout.

For that, it is essential to understand the 'flow' CSS property. It is THE major method for construting layouts in Sciter. Essentially it is the equivalent of CSS3 Flexbox layouting, but it has different naming and behavior (docs here).

The 'flow' property dictates how children of the element will be positioned inside it. For our demo, we only use the following 'flow' modes:

  • horizontal: position elements horizontally, from left-to-right (the reverse in RTL layouts)
  • vertical: position elements vertically, from top-to-bottom
  • stack: position elements one above the other

The 'vertical' value we use says to layout element vertically, one bellow the other, in rows, no matter if its inline or a block element. The 'horizontal' value, of course, place elements horizontally, one beside the other. You use it, for example, to create toolbars.

One aspect of the 'horizontal' flow is that you can reverse the standard left-to-right direction to right-to-left:

div
{
	flow: horizontal;
	direction: rtl;
}

So 'vertical' and 'horizontal' are just the standard method to lay elements linearly (a linear layout).


What's the point with flow: stack?

The arrangement achieved with flow: stack is simply a stack of layers, as we have with visual layers in Photoshop.

It is an alternative and better approach than using position: absolute as it allows to set the x/y alignment of its childs by using horizontal-align and vertical-align, which is much better than using CSS hacks.

TIScript: Populating the page with JSON data

Data to fill our board will definitely come from a dynamic/database source, so we need to resort to scripting.

As a start, I hard-coded the JSON data in script. The data variable holds and array with an object for every column of our board, and each of these object holds a cards field with an array of the cards inside it:

var data = [
	{
		board-name: "Basics",
		cards: [
			{ t: "Welcome to Trello!" },
			{ t: "This is a card." },
			{ t: "Click on a card to see what's behind it." },
			{ t: "You can attach pictures and files...", a: "taco.png" },
			{ t: "... any kind of hyperlink ..." },
			{ t: "... or checklists." }
		]
	},
	...
];

Then I simply put the code that populates our page from this JSON data. It is simply dynamically creating the HTML that displays it to user:

function Setup()
{
	var el_main = $(main);
	for(var s in data)
	{
		var el_section = self#tpl-list[0].clone();
		el_main.insert(el_section, el_main.length - 2);
		el_section.$(.list-header span).text = s#board-name;

		for(var c in s.cards)
		{
			var el_card = self#tpl-card[0].clone();
			el_section.$(ul).append(el_card);
			el_card.$(.card-title).text = c.t;
			if(c.a)
			{
				el_card.$(.card-cover).@#src = c.a;
			}
		}
	}
}
Setup();

TIScript: horizontall scrolling

The main area is supposed to overflow horizontally, that is, scrollbars must appear when content can't fit the window's width. In CSS we declare:

html { overflow: hidden; }
body { overflow-x: auto; }

And for beeing clever, we let the user use the mousel wheel to horizontally scroll it:

$(body).subscribe(function(evt) {
	this.scrollTo(this.scroll(#left)-10*evt.wheelDelta, 0);
}, Event.MOUSE, Event.MOUSE_WHEEL);

By default, Sciter only supports vertically scrolling the page with the wheel.

Next time

Next time we’ll look at the drag'n'drop implementation:

  • Lists drag'n'drop
  • Cards drag'n'drop

The best way to learn is by playing. If you have some Sciter sample and would like it to be showcased here, be my guest!

Aug
25
1 years ago

Wednesday CODE: transitions joy

0 comments

Welcome to our first Wednesday CODE section, though it is thursday. Check our Intro post to know more about it.

For me, doing this examples will be just a lot of fun, so it is simply a pleasure to be sharing my knowledge with everyone.

Without further ado, out first installment is about CSS transitions. Our example will be the following.

In web-terms, we usually call those big headers as Hero (or sometimes Jumbotron). In our example, when you move your mouse hover, it animates the background and the image displaying.

Download source-code / GitHub

Test DEMO with this link: (how to run it)

Drag-me to OmniFiddler


Is Sciter, for creating such animations, which are pretty simple for instance, you can make them just using CSS, no scripting required.

In our example, the two animations are defined this way:

section:hover
{
	background-position: -15px;
	background-color: #5ec8f7;
	transition:
		background-position(quart-out, 0.5s, quart-in)
		background-color(quad-out, 0.3s, quad-in, 0.5s);
}
section:hover img
{
	foreground-position: 0 0;
	transition: foreground(quart-out, 0.5s, quart-in);
}

Essentially we are defining two transitions for when the user hovers the containing <section> that wraps our Hero area which embodies the following HTML:

<section>
	Welcome to Wednesday CODE! <img src="http://misoftware.rs/Content/img/logo_mi.png" />
</section>

In order to declare these animations, you must understand the CSS syntax behind it. And actually, it's simply all about the transition CSS propery.

But where can I look for the docs describing the transition syntax? It is hidden in the SDK, at \doc\content\css\css-transition-sciter.htm. It states about the transition property:

"The transition attribute accepts single value or list of values - functions describing animated transformation of CSS attributes between initial state and the state described by  the rule where the transition is defined."

So, given this declaration:

div:hover
{
    width: 200px;
    height: 200px;
    transition: width(linear,400ms)
                height(linear,400ms);
}

We are essentially saying that when we :hover the <div>, it will gain a new width and height value, however, these changes in the element layout must be animated.

Note that the properties that you want to animate (in this case width and height) must be animatable. That is, like in standard browser, some properties are animatable, others are not.

Animatable properties can change gradually from one value to another, normally these are all properties where the values is a size, number, percentage or color. Unfornutelly I couldn't find a list of supported animatable properties, so you must normmally Test/Run to see if it does animates.

So, our element will animate its width and height when it gains the :hover state. But not only that. It will also animate when it looses the :hover state. That is, a transition: declaration by default sets the animation to play when element start matching or stop matching the CSS selector where the transition: is declared. You can however specify if you want to play the animation in just one of the directions.

Then, we have the transition, which says how our property animates in two aspects:

  • transition easing function
  • duration of the transition

The duration is how long it takes to play the in or out transition. The transition easing function is a math function saying how to ease the transition, you can understand it by looking at \samples\animations-transitions-css\easing-functions.htm in SDK. There you will get all available easing functions:

linear, quad-in, quad-out, quad-in-out, cubic-in, cubic-out, cubic-in-out, quart-in, quart-out, quart-in-out, quint-in, quint-out, quint-in-out, sine-in, sine-out, sine-in-out, expo-in, expo-out, expo-in-out, circ-in, circ-out, circ-in-out, elastic-in, elastic-out, elastic-in-out, back-in, back-out, back-in-out, bounce-in, bounce-out, bounce-in-out

Transitions are a powerfull concept, and I tried here to make a brief technical introduction of the syntax, and also pointed where you can look for more info. Yet, there are many more details to explore about transitions, but which are irrelevant for you to Get Started. That is, you are now able to add animations to Sciter pages!