Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pcom/notite-cb
  • daniel.ghindea/notite-cb
  • stefania.tunaru/notite-cb
  • ioana.ionescu2209/notite-cb
  • razvan_gabriel.serb/notite-cb
  • alexandru.trifu2712/notite-cb
6 results
Show changes
Commits on Source (2)
Showing
with 3966 additions and 118 deletions
......@@ -8,7 +8,10 @@
- [ Nivelul Fizic](curs2/curs.md)
- [ DataLink ](curs3/Cursul3_Serb_Razvan_Gabriel.md)
- [ Detecția și corectarea erorilor](curs4/curs.md)
- [ Networking](curs5/curs.md)
- [ Nivelul rețea](curs6/curs.md)
- [ Protocolul UDP. Nivelul Transport](curs7/curs.md)
- [ Nivelul Transport. Fereastra glisantă. Retransmisii](curs8/curs.md)
- [ Protocolul TCP](curs9/curs.md)
- [ Congestion Control](curs11/curs.md)
- [ World Wide Web](curs12/Cursul12_Serb_Razvan_Gabriel.md)
......
# Nivelul rețea
# Nivelul rețea
<!-- TODO refine this -->
# Legături de date. Detecția și corectarea erorilor.
Din diverse cauze, în timpul transmiterii de date pot apărea fenomene ce duc la coruperea biților, cu alte cuvinte, la inversarea valorii acestora. Pentru a contracara acest fenomen și pentru a menține consistența datelor transmise se pot aplica două soluții:
> - mecanisme de *detecție*
> - mecanisme de *corecție*
Ambele metode se bazează pe adăugarea de "redundanță" în cadrul frame-urilor transmise, adică introducerea unor biți adiționali ce ajută la identificarea erorilor.
Principala diferență între cele două constă în ce se întâmplă cu pachetul la receptare. Mecanismul de detecție duce la aruncarea pachetului primit și trimiterea unei cereri de retransmisie, pe când cel de corecție aplică un set de reguli pentru a corecta erorile.
> Pe legături de distanță mică poate fi mult mai eficient să retrimitem un pachet decât să încercăm să-l corectăm.
```
Ethernet:
ETH HEADER PAYLOAD FCS - frame check sequence = 32 bits
______________________ _____________ _____
|-----|-----|----------|-------------|-----|
| DST | SRC | ETH TYPE | | |
|-----|-----|----------|-------------|-----|
↳ biți redundanți
```
<!-- TODO explain FCS -->
## Bitul de paritate
![parity bit](parity_bit.png)
Dacă se vrea %n cu n > 2, sunt necesari biți redundanți suplimentari.
## Checksum
Checksum este o metodă de detecție ce constă în însumarea octeților mesajului ce trebuie transmis.
Pe send se trimite ~CHECKSUM (checksum negat), iar pe receive se mai calculează odată CHECKSUM pe mesajul primit.
> Mesajul este corect <=> ~CHECKSUM + CHECKSUM = 0
Implementare checksum (din laborator):
```c
uint8_t simple_csum(uint8_t *buf, size_t len)
{
if (!buf) return 0;
uint8_t sum = 0;
for (int i = 0; i < len; i++) {
sum += buf[i];
}
return sum % 256;
}
```
## Ciclic Redundancy Check
Detectează orice rafală (secvență de biți consecutivi) de erori cu lungime < 32 biți și orice număr impar de erori.
Implementare a CRC32 (din laborator):
```c
uint32_t crc32(uint8_t *buf, size_t len)
{
uint32_t crc = ~0;
const uint32_t POLY = 0xEDB88320;
for (int i = 0; i < len; i++) {
crc ^= *buf++;
for (int bit = 0; bit < 8; bit++) {
if (crc & 1)
crc = (crc >> 1) ^ POLY;
else
crc >>= 1;
}
}
crc = ~crc;
return crc;
}
```
## Cod corector de erori
```
1 1 0 0 1 1 0 0 | -> Se ia bitul majoritar
/ \ / \ / \ / \ / \ / \ / \ / \ | => orice eroare de un singur bit
111 110 000 000 111 101 010 000 | va fi garantat corectată
\ / \ / \ / \ / \ / \ / \ / \ / |
1 1 0 0 1 1 0 0 |
```
## Cod Hamming
Inventat de [Richard Hamming](https://en.wikipedia.org/wiki/Richard_Hamming) în 1950, codul Hamming este o metodă de corectare a erorilor ce constă în aplicarea următorilor pași:
### Pentru codificare:
- Codificarea în sistem binar a pozițiilor biților
- Pe pozițiile care nu au index putere a lui 2 se vor pune biții corespunzători mesajul de transmis (biți de date)
- Pe pozițiile cu index putere a lui 2 urmează să se regăsească biții de paritate ce vor fi calculați astfel:
- Se reține poziția pe care se află valoarea 1 în reprezentarea binară a indexului bitului de paritate
- Se execută XOR între toți biții de date ce au în reprezentarea binară a indexului valoarea 1 pe aceeași poziție cu cea anterior reținută
- Rezultatul final reprezintă valoarea bitului de paritate
- Se reia procesul pentru fiecare bit de paritate
- Odata găsiți acești biți mesajul a fost codificat și este gata să fie transmis
### Pentru corecție:
- La recepție este posibil ca pe parcursul transmisiei să se fi corupt unul sau mai mulți biți. Codul Hemming poate corecta orice eroare de maxim 2 biți.
- Pentru a face asta se recalculează biții de paritate, iar indicele bitului corupt va fi egal cu suma indicilor biților de paritate care au ieșit diferit după recalculare.
### Exemplu Hemming(7,4)
<video controls src="video.mp4" title="Hemming code video"></video>
d - bit de date
r - bit de paritate
*If it's too fast you can adjust the playback speed.
---
### Bibliografie
* [Computer Networking : Principles, Protocols and Practice](https://www.computer-networking.info/2nd/html/principles/reliability.html)
* [Networking tutorial](https://www.youtube.com/playlist?list=PLowKtXNTBypH19whXTVoG3oKSuOcw_XeW), primele 6 clipuri.
* [Hamming code](https://en.wikipedia.org/wiki/Hamming_code)
# Legături de date. Detecția și corectarea erorilor.
Din diverse cauze, în timpul transmiterii de date pot apărea fenomene ce duc la coruperea biților, cu alte cuvinte, la inversarea valorii acestora. Pentru a contracara acest fenomen și pentru a menține consistența datelor transmise se pot aplica două soluții:
> - mecanisme de *detecție*
> - mecanisme de *corecție*
Ambele metode se bazează pe adăugarea de "redundanță" în cadrul frame-urilor transmise, adică introducerea unor biți adiționali ce ajută la identificarea erorilor.
Principala diferență între cele două constă în ce se întâmplă cu pachetul la receptare. Mecanismul de detecție duce la aruncarea pachetului primit și trimiterea unei cereri de retransmisie, pe când cel de corecție aplică un set de reguli pentru a corecta erorile.
> Pe legături de distanță mică poate fi mult mai eficient să retrimitem un pachet decât să încercăm să-l corectăm.
```
Ethernet:
ETH HEADER PAYLOAD FCS - frame check sequence = 32 bits
______________________ _____________ _____
|-----|-----|----------|-------------|-----|
| DST | SRC | ETH TYPE | | |
|-----|-----|----------|-------------|-----|
↳ biți redundanți
```
<!-- TODO explain FCS -->
## Bitul de paritate
![parity bit](parity_bit.png)
Dacă se vrea %n cu n > 2, sunt necesari biți redundanți suplimentari.
## Checksum
Checksum este o metodă de detecție ce constă în însumarea octeților mesajului ce trebuie transmis.
Pe send se trimite ~CHECKSUM (checksum negat), iar pe receive se mai calculează odată CHECKSUM pe mesajul primit.
> Mesajul este corect <=> ~CHECKSUM + CHECKSUM = 0
Implementare checksum (din laborator):
```c
uint8_t simple_csum(uint8_t *buf, size_t len)
{
if (!buf) return 0;
uint8_t sum = 0;
for (int i = 0; i < len; i++) {
sum += buf[i];
}
return sum % 256;
}
```
## Ciclic Redundancy Check
Detectează orice rafală (secvență de biți consecutivi) de erori cu lungime < 32 biți și orice număr impar de erori.
Implementare a CRC32 (din laborator):
```c
uint32_t crc32(uint8_t *buf, size_t len)
{
uint32_t crc = ~0;
const uint32_t POLY = 0xEDB88320;
for (int i = 0; i < len; i++) {
crc ^= *buf++;
for (int bit = 0; bit < 8; bit++) {
if (crc & 1)
crc = (crc >> 1) ^ POLY;
else
crc >>= 1;
}
}
crc = ~crc;
return crc;
}
```
## Cod corector de erori
```
1 1 0 0 1 1 0 0 | -> Se ia bitul majoritar
/ \ / \ / \ / \ / \ / \ / \ / \ | => orice eroare de un singur bit
111 110 000 000 111 101 010 000 | va fi garantat corectată
\ / \ / \ / \ / \ / \ / \ / \ / |
1 1 0 0 1 1 0 0 |
```
## Cod Hamming
Inventat de [Richard Hamming](https://en.wikipedia.org/wiki/Richard_Hamming) în 1950, codul Hamming este o metodă de corectare a erorilor ce constă în aplicarea următorilor pași:
### Pentru codificare:
- Codificarea în sistem binar a pozițiilor biților
- Pe pozițiile care nu au index putere a lui 2 se vor pune biții corespunzători mesajul de transmis (biți de date)
- Pe pozițiile cu index putere a lui 2 urmează să se regăsească biții de paritate ce vor fi calculați astfel:
- Se reține poziția pe care se află valoarea 1 în reprezentarea binară a indexului bitului de paritate
- Se execută XOR între toți biții de date ce au în reprezentarea binară a indexului valoarea 1 pe aceeași poziție cu cea anterior reținută
- Rezultatul final reprezintă valoarea bitului de paritate
- Se reia procesul pentru fiecare bit de paritate
- Odata găsiți acești biți mesajul a fost codificat și este gata să fie transmis
### Pentru corecție:
- La recepție este posibil ca pe parcursul transmisiei să se fi corupt unul sau mai mulți biți. Codul Hemming poate corecta orice eroare de maxim 2 biți.
- Pentru a face asta se recalculează biții de paritate, iar indicele bitului corupt va fi egal cu suma indicilor biților de paritate care au ieșit diferit după recalculare.
### Exemplu Hemming(7,4)
<video controls src="video.mp4" title="Hemming code video"></video>
d - bit de date
r - bit de paritate
*If it's too fast you can adjust the playback speed.
---
### Bibliografie
* [Computer Networking : Principles, Protocols and Practice](https://www.computer-networking.info/2nd/html/principles/reliability.html)
* [Networking tutorial](https://www.youtube.com/playlist?list=PLowKtXNTBypH19whXTVoG3oKSuOcw_XeW), primele 6 clipuri.
* [Hamming code](https://en.wikipedia.org/wiki/Hamming_code)
# Nivelul Transport. Fereastra glisantă. Retransmisii
## Nivelul transport
O rețea este proiectată cu scopul ca mai multe aplicații de pe host-uri diferite să poată schimba informații între ele. Pentru a garanta că fiecare pachet primit ajunge la aplicația căruia îi este destinat se utilizează conceptul de *porturi*.
> Un **port** este o entitate virtuală (un număr asignat unei conexiuni) ce face legătura între **host** și **aplicație**.
<!-- TODO add link to UDP & TCP-->
Astfel, la acest nivel are loc procesul de demultiplexare (vezi [UDP](./../curs7/curs.md)) care asigură simplul transport al datelor. În plus, mai este necesară o transmitere sigură (să ajungă datele), în ordine și care să se facă o singură dată (vezi [TCP](../curs9/curs.md)).
![transport](./img/transport.png)
### Ajustarea vitezei de transmisie
Protocolul de transport trebuie să se asigure că:
- transmite cât se poate de repede
- împarte echitabil resursele
- folosește eficient resursele
```
lungime fir
latența ≃ ───────────────── d = delay (latență)
viteza luminii B = bandwidth (bit/s)
D = dimensiunea fișierului
10 000 km
ex: București-SUA => d = ─────────────── = 1/30s = 33ms
3 000 000 km/s
RTT = 2*33ms = 66ms
▭ - pachet 1Mb
TS = D/B
________________________
B=1 Gbps |______________________| ▭ =>TS = 1Mb/1Gbps = 8ms
________________________
| |
| |
B=10 Gbps | | ▭ =>TS = 1Mb/10Gbps = 0.8ms
| |
|______________________|
TT = TS + d = 33+8 sau 33+0.8 = 41ms sau 33.8ms
Td(D, B, d) = D/B + d
```
- **Latența** (timpul în care semnalul ajunge de la un capăt la celălalt al firului) unei transmisii depinde de lungimea firului (în cazul transmisiei prin fibră optică).
- **Round Trip Time** (RTT) este durata de timp necesară transmiterii unui pachet și primirii unui răspuns (dublul latenței).
- **Timpul de serializare** (TS) este timpul necesar de a lua un pachet și a-l pune pe fir.
- **Timpul de transfer** (TT) este timpul necesar de a transmite un pachet.
- **Timpul de download** (Td) este timpul necesar de a descarca un fișier.
Un mecanism prin care ne asigurăm că pachetele sunt transmise în ordine și o singură dată este mecanismul **START-STOP**. El presupune trimiterea unui pachet, așteptarea unui răspuns și, în funcție de răspuns, retrimiterea pachetului sau trimiterea pachetului următor.
## Fereastra glisantă
> Fereastră = numărul de pachete aflate în zbor pentru care nu am primit ACK.
>
> ACK = informație de control (acknowledged)
Problema mecanismului start-stop este că de la o transmisie la alta cablul ar fi gol, iar astfel s-ar irosi mult timp. O soluție este să trimitem mai multe pachete pe fir fără a primi un răspuns.
![fereastra](./img/fs.png)
Astfel se poate ajusta cantitatea de date transmisă astfel încât transmisia să se facă în mod optim.
<!-- maybe adjust this graph? : https://www.desmos.com/calculator/obyafdn8r6 -->
<iframe src="https://www.desmos.com/calculator/gewcpyhwkq?embed" width="700" height="500" style="border: 1px solid #ccc" frameborder=0></iframe>
<iframe class="is-fullwidth" height="730" marginheight="0" marginwidth="0" src="sim/index.html">
</iframe>
[Mai multe animații aici](https://www2.tkn.tu-berlin.de/teaching/rn/animations/gbn_sr/)
```
BPD = B * d (Bandwidth Delay Product) = MTU * d / TS(MTU, B)
MTU = Maximum Transmission Unit
d = 20ms |
B = 100 Mbps | => BDP = 100Mbps * 20ms = 250 Kb
d = 20ms |
B = 1 Gbps | => BDP = 2,5 Mb
windowSize = [BPD / datagramSize] , datagramSize <= 1500 bytes
```
Pentru a asigura o transmisie optimă a datelor (cât mai mult, cât mai rapid, fără pierderi, la fel pentru toți) este necesară o modalitate de a regla dinamic mărimea ferestrei glisante. Vezi capitolul [Congestion Control](./../curs11/curs.md).
## Retransmisii
Dat fiind că legăturile de date sunt predispuse să aibă **pierderi**, sunt necesare mecanisme ce asigură un transfer corect al pachetelor de date (complet și în ordine).
- _**Cum știi că un pachet s-a pierdut?**_ De obicei, pachetele ce urmează să fie trimise sunt acumulate într-un `sendBuffer`, iar atunci când sunt trimise pe fir le este asociat un timer. Dacă timpul de așteptare depășește valoarea **RTO** (**Retransmit TimeOut**), atunci pachetul poate fi considerat pierdut pe drum și este necesară retransmiterea lui.
- **_RTO nu poate fi foarte agresiv_**, căci în cazul unei congestii în rețea durata de transmisie este inevitabil mai lungă decât într-o rețea "goală", iar atunci există șanse ca pachetul să fie fals declarat pierdut.
Mecanismul de retransmisie depinde de capacitatea receiverului de a prelucra informația primită:
1. **No receive buffer** - La receptor, orice pachet care nu este așteptat va fi aruncat. Astfel, pachetele vor fi primite în ordine, dar pachetele neașteptate (care ar trebui să vină după pachetul așteptat, dar ajung înaintea lui) vor fi aruncate până la primirea pachetului așteptat. (**GO-BACK-N**)
![no_buff](./img/no_buff.png)
2. **Receive buffer** - La receptor, fiecare pachet este salvat într-un buffer. Astfel, pachetele neașteptate nu vor mai fi aruncate, ci vor fi salvate pe poziția lor corespunzătoare, pachetul așteptat fiind și el salvat ulterior, când este primit, în fața pachetelor ce ar fi trebuit să vină după el.
![buff](./img/buff.png)
### Bibliografie
- [Computer Networking : Transport layer](https://www.computer-networking.info/2nd/html/principles/transport.html#the-transport-layer)
<!-- ```
B1 ___________ B2
Src o--------| |--------o Dst
d1 |_________| d2
↳ router
``` -->
\ No newline at end of file
src/curs8/img/buff.png

17.5 KiB

src/curs8/img/fs.png

165 KiB

src/curs8/img/grafic.png

63.4 KiB

src/curs8/img/no_buff.png

22 KiB

src/curs8/img/transport.png

122 KiB

// src = http://paulirish.com/2011/requestanimationframe-for-smart-animating/
window.cancelRequestAnimFrame = ( function() {
return window.cancelAnimationFrame ||
window.webkitCancelRequestAnimationFrame ||
window.mozCancelRequestAnimationFrame ||
window.oCancelRequestAnimationFrame ||
window.msCancelRequestAnimationFrame ||
clearTimeout;
} )();
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
return window.setTimeout(callback, 1000 / 60);
};
})();
/* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*/
// Inspired by base2 and Prototype
(function(){
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function(){};
// Create a new Class that inherits from this class
Class.extend = function(prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if ( !initializing && this.init )
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
function getRandom(min, max) {
if(min > max) {
return -1;
}
if(min == max) {
return min;
}
var r;
do {
r = Math.random();
}
while(r == 1.0);
return min + parseInt(r * (max-min+1));
}
function rangeInputCompability(){
// Check if browser supports <input type=range/>
var i = document.createElement("input");
i.setAttribute("type", "range");
var rangeNotSupported = (i.type === "text");
delete i;
// If browser doesn't support <input type=range/>
// then use jQuery UI to display them
if(rangeNotSupported) {
// loop through all <input type=range/>
// on the page
$("input[type=range]").each(function(){
var range = $(this);
// Create <div/> to hold jQuery UI Slider
var sliderDiv = $("<div/>");
sliderDiv.width(range.width());
// Insert jQuery UI Slider where the
// <input type=range/> is located
range.after(
sliderDiv.slider({
// Set values that are set declaratively
// in the <input type=range/> element
min: parseFloat(range.attr("min")),
max: parseFloat(range.attr("max")),
value: parseFloat(range.val()),
step: parseFloat(range.attr("step")),
// Update the <input type=range/> when
// value of slider changes
slide: function(evt, ui) {
range.val(ui.value);
var self = range[0];
eval(range.attr("onchange").replace(/this/g, "self"));
},
change: function(evt, ui) {
// set <input type=range/> value
range.val(ui.value);
var self = range[0];
eval(range.attr("onchange").replace(/this/g, "self"));
}
})
).
// Hide <input type=range/> from display
hide();
});
}
}
/*function Timer(callback, delay) {
var timerId, start, remaining = delay;
this.pause = function() {
window.clearTimeout(timerId);
remaining -= new Date() - start;
};
this.resume = function() {
start = new Date();
timerId = window.setTimeout(callback, remaining);
};
this.resume();
}*/
var runningTimers = new Object();
function Timer(callback, delay) {
var timerId, start, remaining = delay, running = false, stopped = false;
this.pause = function() {
if(running == false)
return;
window.clearTimeout(timerId);
remaining -= new Date() - start;
running = false;
};
this.stop = function(){
this.pause();
stopped = true;
if(typeof runningTimers[timerId] !== 'undefined')
delete runningTimers[timerId];
}
this.start = function() {
if(running || stopped)
return;
if(remaining < 0){
this.stop();
}
start = new Date();
running = true;
timerId = window.setTimeout(callback, remaining);
runningTimers[timerId] = this;
};
this.stopAll = function(){
for(var i in runningTimers){
runningTimers[i].stop();
}
}
this.start();
}
function stopAllTimers(){
for(var e in runningTimers){
runningTimers[e].stop();
}
}
String.prototype.trimRight = function(numChars){
return this.substr(0, this.length-numChars);
}
function disableFormItems(disable, group){
var groupClass;
if(typeof group == 'undefined')
groupClass = '';
else
groupClass = '.disable-group'+group;
if(disable === true){
var e = $('.config .form-item.disable'+groupClass)
.addClass('disabled');
e.find('input, select').filter(':not([disabled])').attr('disabled', 'disabled').addClass('temp-disabled');
e.find('div.ui-slider').slider( "option", "disabled", true );
}
else{
var e = $('.config .form-item.disable'+groupClass)
.removeClass('disabled', 300, 'linear');
e.find('input, select').filter('.temp-disabled').removeAttr('disabled');
e.find('div.ui-slider').slider( "option", "disabled", false );
}
}
function checkFeatures(args){
args = $.extend({
inlinesvg: false,
canvas: false
}, args);
var errors = Array();
if(args.inlinesvg && !(Modernizr.inlinesvg && Modernizr.svg))
errors.push('inline svg');
if(args.canvas && !Modernizr.canvas)
errors.push('canvas element');
if(errors.length == 0)
return;
var msg = $('<div class="browser-features-missing"><h1>Warning</h1><p>Your Browser does not support all features needed to run this animation.</p><p>Features Missing: <ul class="features-missing"></ul></p><p>Please use a modern Browser that supports these features.</p></div>');
for(var i = 0; i < errors.length; i++){
msg.children('ul.features-missing').prepend('<li>'+errors[i]+'</li>');
}
$('body').prepend(msg);
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Pause jQuery plugin v0.1
*
* Copyright 2010 by Tobia Conforto <tobia.conforto@gmail.com>
*
* Based on Pause-resume-animation jQuery plugin by Joe Weitzel
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or(at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
(function(){var e=jQuery,f="jQuery.pause",d=1,b=e.fn.animate,a={};function c(){return new Date().getTime()}e.fn.animate=function(k,h,j,i){var g=e.speed(h,j,i);g.complete=g.old;return this.each(function(){if(!this[f]){this[f]=d++}var l=e.extend({},g);b.apply(e(this),[k,e.extend({},l)]);a[this[f]]={run:true,prop:k,opt:l,start:c(),done:0}})};e.fn.pause=function(){return this.each(function(){if(!this[f]){this[f]=d++}var g=a[this[f]];if(g&&g.run){g.done+=c()-g.start;if(g.done>g.opt.duration){delete a[this[f]]}else{e(this).stop();g.run=false}}})};e.fn.resume=function(){return this.each(function(){if(!this[f]){this[f]=d++}var g=a[this[f]];if(g&&!g.run){g.opt.duration-=g.done;g.done=0;g.run=true;g.start=c();b.apply(e(this),[g.prop,e.extend({},g.opt)])}})}})();
This diff is collapsed.
/**
* Generic elements
*/
body {
margin: 0;
padding: 10px;
background: #fff;
font: 12.2px Verdana, sans-serif;
color: #000;
text-align: left;
}
input, textarea, select {
color: #000;
font-size: 1em;
}
h1,h2,h3,h4,h5,h6 {
margin: 0;
padding: 0;
font-weight: normal;
font-family: Helvetica, Arial, sans-serif;
}
h1 {
font-size: 1.7em;
}
h2 {
font-size: 1.6em;
line-height: 130%;
}
h3 {
font-size: 1.6em;
}
h4 {
font-size: 1.3em;
}
h5 {
font-size: 1.2em;
}
h6 {
font-size: 1.1em;
}
quote, code, fieldset {
margin: .5em 0;
}
code, pre, kbd {
font-size: 115%;
}
p {
margin: 0.6em 0 1.2em;
padding: 0;
}
a:link,
a:visited {
color: #00adef;
text-decoration: underline;
}
a:hover {
color: #141309;
text-decoration: underline;
}
a:active,
a.active {
color: #555555;
}
hr {
margin: 0;
padding: 0;
border: none;
height: 1px;
background: #4f4f4f;
}
ul, ol {
margin: 0.5em 0 1em;
padding: 0 0 0 1.5em; /* LTR */
}
dl {
margin: 0.5em 0 1em 1.5em; /* LTR */
}
dl dt {
}
dl dd {
margin: 0 0 .5em 1.5em; /* LTR */
}
img,
a img {
border: none;
}
table, td, th{
border-collapse: collapse;
border: 1px solid #00ADEF;
padding: 2px;
vertical-align: top;
}
th{
font-size: 0.8em;
text-align: left;
background: #ffffff url(../images/gradient-inner.png) repeat-x 0 0;
padding: 3px;
}
.browser-features-missing{
background-color: #FFBDBE;
border: 3px solid red;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
padding: 15px;
margin-bottom: 32px;
}
/* config */
.config, .legend, .def{
background: #ffffff url(../images/gradient-inner.png) repeat-x 0 0;
border: 2px solid #00adef;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
margin: 10px 10px 10px 0px;
padding: 1em 1em 1.5em;
}
.config{
-webkit-column-width: 20em;
-webkit-column-gap: 20px;
-moz-column-width: 20em;
-moz-column-gap: 20px;
column-width: 20em;
column-gap: 20px;
}
.config > .form-item{
margin-bottom: 1em;
margin-top: 1em;
padding-left: 2em;
break-inside: avoid;
-moz-column-break-inside: avoid;
-webkit-column-break-inside: avoid;
-moz-break-inside: avoid;
display: inline-block;
width: 20em;
}
.config .form-item.disable.disabled{
background-color: silver;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
/* keep heading out of column layout */
.config > h2:first-child{
position: absolute;
}
.config > *:nth-child(2){
margin-top: 2.5em;
}
.config > .form-item > h3{
font-size: inherit;
font-weight: bold;
font-family: inherit;
margin-left: -2em;
}
.config label{
display: block;
}
.config label.option{
display: inline;
font-weight: normal;
}
.config .description{
font-size: 0.92em;
color: #000;
line-height: 150%;
margin-top: 0.4em;
margin-bottom: 0.75em;
}
.config input{
font-size: 1em;
}
/* legend */
.legend{
float: left;
}
.legend table, .legend td, .legend th{
border-style: none;
}
/* simulation */
.simulation{
-moz-box-shadow: 10px 10px 5px #888;
-webkit-box-shadow: 10px 10px 5px #888;
box-shadow: 10px 10px 5px #888;
padding: 1em 0 1em 0;
border: 1px solid black;
overflow: hidden;
}
/* input range fix for android stock browser (http://tiffanybbrown.com/2012/02/07/input-typerange-and-androids-stock-browser/)*/
input[type=range]{
background: #D8D8D8;
height: auto;
}
input[type=range]::-webkit-slider-thumb{
background: #00adef;
height: 30px;
width: 30px;
border-radius: 30px;
}
@media screen and (min-width: 1200px){
/*body{
padding-left: 5em;
}
body > h1:first-child{
-moz-transform: rotate(90deg);
-moz-transform-origin: left bottom;
-o-transform: rotate(90deg);
-o-transform-origin: left bottom;
-webkit-transform: rotate(90deg);
-webkit-transform-origin: left bottom;
transform: rotate(90deg);
transform-origin: left bottom;
font-size: 5em;
margin-left: -1.2em;
position: absolute;
top: -1em;
}*/
}
/*@media handheld and (orientation: landscape), screen and (orientation: landscape) and (max-height: 550px)
, screen and (max-width: 550px) {
body.mobile > *:not(.simulation){
display: none;
}
body.mobile .simulation{
margin: 0px;
border: 0px;
-moz-box-shadow: 0 0 0 0 #888;
-webkit-box-shadow: 0 0 0 0 #888;
box-shadow: 0 0 0 0 #888;
}
body.mobile{
}
}*/
\ No newline at end of file