/*!
* Check if an element is out of the viewport
* (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com
* @param {Node} elem The element to check
* @return {Object} A set of booleans for each side of the element
*/
var isOutOfViewport = function (elem) {
// Get element's bounding
var bounding = elem.getBoundingClientRect();
// Check if it's out of the viewport on each side
var out = {};
out.top = bounding.top < 0;
out.left = bounding.left < 0;
out.bottom = bounding.bottom > (window.innerHeight || document.documentElement.clientHeight);
out.right = bounding.right > (window.innerWidth || document.documentElement.clientWidth);
out.any = out.top || out.left || out.bottom || out.right;
out.all = out.top && out.left && out.bottom && out.right;
return out;
};
// from bottom to top
// console.table({
// 'tooltipHeight': $tooltip.height(),
// 'offsetTop': offsetPos.y,
// 'positionTop': position.top,
// 'windowHeight': $(window).height(),
// 'documentHeight': $(document).height(),
// 'scrollTop': $(window).scrollTop(),
// });
if (offsetPos.y - $(window).scrollTop() + $tooltip.outerHeight(true) > $(window).height())
{
var moveUp = offsetPos.y - $tooltip.height() - 35;
$tooltip.css({
top: moveUp + "px"
})
}
// right side
var offset = $(this).offset();
var position = $(this).position();
var offsetPos = {
x: offset.left,
y: offset.top + 35,
}
// prevent overlapping on the right edge
if (offsetPos.x + tooltipSize.w >= winSize.w)
{
offsetPos.x = winSize.w - tooltipSize.w - gutter;
}
<?php
include "1.php";
/*
Definice
--------
Návrhový vzor Proxy kontroluje přístup k objektu pomocí zástupce, který se používá
místo vlastního objektu.
Pro implementaci zástupce typu Protection Proxy je nutné provést následující
kroky:
1. Vytvořit třídu, která implementuje veškerá rozhraní implementované třídou,
jejíž instance mají být chráněné.
2. Ve všech metodách delegovat volání na objekt, který provede požadovanou
úlohu.
3. Vytvořit potomka třídy z bodu 2 a v relevantních metodách implementovat
kontrolní mechanizmy.
*/
abstract class PublicationProxy implements Publication
{
protected $publication;
public function __construct(Publication $publication)
{
$this->publication = $publication;
}
public function open()
{
return $this->publication->open();
}
public function close()
{
return $this->publication->close();
}
public function setPageNumber($page)
{
return $this->publication->setPageNumber($page);
}
public function getPageNumber()
{
return $this->publication->getPageNumber();
}
public function getDailyRate($days = 1)
{
return $this->publication->getDailyRate($days);
}
public function getCategory()
{
return $this->publication->getCategory();
}
public function getPageCount()
{
return $this->publication->getPageCount();
}
}
class PrepaidPublicationProxy extends PublicationProxy
{
protected $startPage;
protected $endPage;
public function __construct(Publication $publication, $startPage, $endPage)
{
parent::__construct($publication);
$this->startPage = $startPage;
$this->endPage = $endPage;
}
public function setPageNumber($page)
{
if ($this->startPage > $page || $this->endPage < $page) {
throw new OutOfRangeException(
$page,
$this->startPage,
$this->endPage
);
}
return $this->publication->setPageNumber($page);
}
}
class OutOfRangeException extends \Exception
{
protected $page;
protected $startPage;
protected $endPage;
public function __construct($page, $startPage, $endPage)
{
$this->page = $page;
$this->startPage = $startPage;
$this->endPage = $endPage;
$this->message = sprintf(
"Požadovaná strana číslo %dse nenachází v předplaceném rozsahu stran %d - %d.",
$this->page,
$this->startPage,
$this->endPage
);
}
public function getPage()
{
return $this->page;
}
public function getStartPage()
{
return $this->startPage;
}
public function getEndPage()
{
return $this->endPage;
}
}
$book = new Book('medicína', 650);
$proxy = new PrepaidPublicationProxy($book, 261, 414);
$proxy->open();
try
{
$proxy->setPageNumber(300);
print "Kniha je otevřená na straně 300.\n";
$proxy->setPageNumber(115);
print "Kniha je otevřená na straně 115.\n";
}
catch (OutOfRangeException $e) {
print $e->getMessage() . "\n";
}
$proxy->close();
/*
Kniha je otevřená na straně 300.
Požadovaná strana číslo 115 se nenachází
v předplaceném rozsahu stran 261-414.
*/
/*!
* jQuery prototypal inheritance plugin boilerplate
* Author: Alex Sexton, Scott Gonzalez
* Further changes: @addyosmani
* Licensed under the MIT license
*/
// myObject - an object representing a concept that you want
// to model (e.g. a car)
var myObject = {
init: function( options, elem ) {
// Mix in the passed-in options with the default options
this.options = $.extend( {}, this.options, options );
// Save the element reference, both as a jQuery
// reference and a normal reference
this.elem = elem;
this.$elem = $(elem);
// Build the DOM's initial structure
this._build();
// return this so that we can chain and use the bridge with less code.
return this;
},
options: {
name: "No name"
},
_build: function(){
//this.$elem.html('<h1>'+this.options.name+'</h1>');
},
myMethod: function( msg ){
// You have direct access to the associated and cached
// jQuery element
console.log("myMethod triggered");
// this.$elem.append('<p>'+msg+'</p>');
}
};
// Object.create support test, and fallback for browsers without it
if ( typeof Object.create !== "function" ) {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
// Create a plugin based on a defined object
$.plugin = function( name, object ) {
$.fn[name] = function( options ) {
return this.each(function() {
if ( ! $.data( this, name ) ) {
$.data( this, name, Object.create(object).init(
options, this ) );
}
});
};
};
// Usage:
// With myObject, we could now essentially do this:
// $.plugin('myobj', myObject);
// and at this point we could do the following
// $('#elem').myobj({name: "John"});
// var inst = $('#elem').data('myobj');
// inst.myMethod('I am a method');
// jQuery Plugin Boilerplate
// A boilerplate for jumpstarting jQuery plugins development
// version 1.1, May 14th, 2011
// by Stefan Gabos
(function($) {
$.pluginName = function(element, options) {
var defaults = {
foo: 'bar',
onFoo: function() {}
}
var plugin = this;
plugin.settings = {}
var $element = $(element),
element = element;
plugin.init = function() {
plugin.settings = $.extend({}, defaults, options);
// code goes here
}
plugin.foo_public_method = function() {
// code goes here
}
var foo_private_method = function() {
// code goes here
}
plugin.init();
}
$.fn.pluginName = function(options) {
return this.each(function() {
if (undefined == $(this).data('pluginName')) {
var plugin = new $.pluginName(this, options);
$(this).data('pluginName', plugin);
}
});
}
})(jQuery);
// USAGE
$(document).ready(function() {
// attach the plugin to an element
$('#element').pluginName({'foo': 'bar'});
// call a public method
$('#element').data('pluginName').foo_public_method();
// get the value of a property
$('#element').data('pluginName').settings.foo;
});
<?php
include "1.php";
/*
Definice
--------
Návrhový vzor Decorator rozšiřuje daný objekt o novou funkčnost nebo změní stávající
metody za běhu programu. Tento návrhový vzor nabízí flexibilní alternativu
k vytváření potomků tříd.
Pro dosažení požadovaného výsledku jsou nutné následující kroky:
1. Vytvořit základní třídu pro dekorátory, která je stejného typu jako objekt,
který má být dekorovaný. Vytvořit potomka této třídy nebo v nové třídě
implementovat všechny metody rozhraní.
2. V základní třídě definovat konstruktor, jemuž bude možné předat dekorovaný
objekt. Tento objekt uložit ve třídě dekorátoru.
3. Implementovat všechny metody základní třídy takovým způsobem, že se
jejich volání bude delegovat na objekt, který se má dekorovat.
4. Implementovat libovolné konkrétní dekorátory, jež jsou potomky třídy
z bodu 3. Konkrétního chování dekorátoru se docílí přepsáním jednotlivých
metod.
5. Kombinací více dekorátorů lze dosáhnout jejich vzájemným dekorováním.
*/
abstract class PublicationDecorator implements Publication
{
protected $publication;
public function __construct(Publication $publication)
{
$this->publication = $publication;
}
public function open()
{
return $this->publication->open();
}
public function close()
{
return $this->publication->close();
}
public function setPageNumber($page)
{
return $this->publication->setPageNumber($page);
}
public function getPageNumber()
{
return $this->publication->getPageNumber();
}
public function getDailyRate($days = 1)
{
return $this->publication->getDailyRate($days);
}
public function getCategory()
{
return $this->publication->getCategory();
}
public function getPageCount()
{
return $this->publication->getPageCount();
}
public function __call($method, $args)
{
return call_user_func_array(
array($this->publication, $method), $args
);
}
public function providesMethod($method)
{
if (method_exists($this->publication, $method))
{
return TRUE;
}
if ($this->publication instanceof PublicationDecorator)
{
return $this->publication->providesMethod($method);
}
return FALSE;
}
public function getPublication()
{
return $this->publication;
}
}
class PublicationDecoratorAppendix extends PublicationDecorator
{
public function getDailyRate($days = 1)
{
$rate = $this->publication->getDailyRate($days);
return $rate + 2;
}
public function getPageCount()
{
$pageCount = $this->publication->getPageCount();
return $pageCount + 30;
}
}
// Použití
$book = new Book('medicína', 100);
$withAppendix = new PublicationDecoratorAppendix($book);
printf("Celkový počet stran s přílohou: %d\n",
$withAppendix->getPageCount()
);
printf("Denní sazba: %.2f Kč\n",
$withAppendix->getDailyRate()
);
/*
Celkový počet stran s přílohou: 130
Denní sazba: 12.00 Kč
*/
// Další decorator
class PublicationDecoratorNews extends PublicationDecorator
{
public function getDailyRate($days = 1)
{
$rate = $this->publication->getDailyRate($days);
return round($rate * 0.8, 2);
}
}
$newsWithAppendix = new PublicationDecoratorNews($withAppendix);
printf("Celkový počet stran s přílohou: %d\n",
$newsWithAppendix->getPageCount()
);
printf("Denní sazba: %.2f Kč\n",
$newsWithAppendix->getDailyRate()
);
/*
Celkový počet stran s přílohou: 130
Denní sazba: 9.60 Kč
*/
/*
Další využití
-------------
Lze doplnit i nové metody
*/
class PublicationDecoratorCd extends PublicationDecorator
{
protected $track = 1;
public function getTrack()
{
return $this->track;
}
public function setTrack($track)
{
$this->track = $track;
}
public function getDailyRate($days = 1)
{
$rate = $this->publication->getDailyRate($days);
return $rate * 1.3;
}
}
$book = new Book('italská kuchyně', 280);
$withCd = new PublicationDecoratorCd($book);
printf("Denní sazba: %.2f Kč\n", $withCd->getDailyRate());
$withCd->setTrack(10);
printf("Aktuální stopa: %d \n", $withCd->getTrack());
/*
Denní sazba: 13.00 Kč
Aktuální stopa: 10
*/
/*
Může vzniknout problém, že jiný dekorátor tyto metody nevidí,
odchytne se to pres __call, ale je to takové magické...
*/
$book = new Book('italská kuchyně', 280);
$withCd = new PublicationDecoratorCd($book);
$newsWithCd = new PublicationDecoratorNews($withCd);
printf("Denní sazba: %.2f Kč\n", $newsWithCd->getDailyRate());
$newsWithCd->setTrack(10);
// printf("Aktuální stopa: %d \n", $newsWithCd->getTrack());
/*
Denní sazba: 10.40 Kč
Aktuální stopa: 10
*/
/*
Dá se to vyřešit lépe...
viz vlastní metoda na existenci providesMethods()
*/
$book = new Book('italská kuchyně', 280);
$withCd = new PublicationDecoratorCd($book);
$newsWithCd = new PublicationDecoratorNews($withCd);
if ($newsWithCd->providesMethod('setTrack'))
{
var_dump($newsWithCd->getPublication());
$newsWithCd->setTrack(30);
}
printf("Aktuální stopa: %d \n", $newsWithCd->getTrack());
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
.blocker
{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
z-index: 1;
padding: 20px;
box-sizing: border-box;
background-color: #000;
background-color: #000000bf;
text-align: center;
}
.blocker::before
{
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.05em;
}
.modal
{
vertical-align: middle;
position: relative;
z-index: 2;
max-width: 500px;
box-sizing: border-box;
width: 90%;
background: #fff;
padding: 15px 30px
}
</style>
</head>
<body>
<!-- https://jquerymodal.com/ -->
<div class="jquery-modal blocker current">
<div class="modal" style="display: inline-block;">
<h1>Hello there!</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p><a href="#close-modal" rel="modal:close" class="close-modal ">Close</a></div>
</div>
</div>
</body>
</html>
<?php
include "1.php";
/*
Návrhový vzor Bridge odděluje rozhraní třídy od její vlastní implementace a umožňuje
provádět jejich změnu nezávisle na sobě.
*/
/*
Definice
--------
Návrhový vzor Bridge odděluje rozhraní třídy od její vlastní implementace a umožňuje
provádět jejich změnu nezávisle na sobě.
Pro dosažení tohoto cíle je nutné provést následující kroky:
1. Definovat rozhraní nezbytné pro jednotlivé implementace.
2. Vytvořit minimálně dvě třídy implementující rozhraní z bodu 1.
3. Vytvořit způsob, jak abstrakci předat konkrétní implementaci.
4. V abstrakci využívat služby implementace z bodu 2 přes rozhraní definované
v bodě 1.
Shrnutí
-------
Návrhový vzor Bridge odděluje abstrakci od její konkrétní implementace a zamezuje
tak zbytečnému nárůstu počtu tříd při předávání implementací. Tento
návrhový vzor řeší podobný problém jako návrhový vzor Adapter, představený
v předchozí kapitole. Rozdíl mezi těmito dvěma vzory je především v tom, že
vzor Bridge se používá již při návrhu aplikace, zatímco vzor Adapter řeší problém,
jak zabezpečit komunikaci již hotových tříd.
*/
interface Storage
{
public function insertPublication($id, Publication $p);
public function fetchPublications();
}
class StorageArray implements Storage
{
protected $publications;
public function insertPublication($id, Publication $p)
{
$this->publications[$id] = $p;
}
public function fetchPublications()
{
return $this->publications;
}
}
// Upravena trida library oproti 1 dilu
abstract class AbstractLibrary
{
protected $rentalActions = array();
protected $debugger;
protected $storage;
public function __construct(Debugger $debugger, Storage $storage)
{
$this->debugger = $debugger;
$this->storage = $storage;
}
protected function debug($message)
{
$this->debugger->debug($message);
}
public function rentPublication(Publication $p, Member $m)
{
$publicationId = array_search($p, $this->getPublications());
if (false === $publicationId) {
throw new UnknownPublicationException();
}
if (!$this->isPublicationAvailable($p)) {
throw new PublicationNotAvailableException();
}
$rentalAction = new RentalAction($p, $m);
$this->rentalActions[] = $rentalAction;
$this->debug(
$m->getName() . ' si vypůjčil publikaci: ' . $p->getCategory()
);
return $rentalAction;
}
public function returnPublication(Publication $p)
{
foreach ($this->rentalActions as $rentalAction)
{
if ($rentalAction->getPublication() !== $p) {
continue;
}
if ($rentalAction->isReturned()) {
continue;
}
$rentalAction->markPublicationReturned();
$this->debug(
$rentalAction->getMember()->getName() .
' vrátil publikaci: ' .
$p->getCategory()
);
return true;
}
return false;
}
public function isPublicationAvailable(Publication $p)
{
foreach ($this->rentalActions as $rentalAction)
{
if ($rentalAction->getPublication() !== $p) {
continue;
}
if ($rentalAction->isReturned()) {
continue;
}
return false;
}
return true;
}
public function generateId()
{
$publications = $this->getPublications();
return 'PUBLICATION-' . count($publications);
}
public function getPublications()
{
return $this->storage->fetchPublications();
}
abstract public function addToLibrary($id, Publication $p);
}
class Library extends AbstractLibrary
{
public function addToLibrary($id, Publication $p)
{
$this->storage->insertPublication($id, $p);
$this->debug('Nová publikace v knihovně: ' . $p->getCategory());
}
}
// Storages
class StorageDatabase implements Storage
{
protected $db;
public function __construct($filename)
{
$this->db = new \SQLiteDatabase($filename, 0666);
$this->initialiseDatabase();
}
public function insertPublication($id, Publication $p)
{
// INSERT TO DB
}
public function fetchPublications()
{
// SELECT FROM DB && FETCH to $publications (array or ...)
return $publications
}
protected function initialiseDatabase()
{
// connection to db
}
}
class StorageArray implements Storage
{
protected $publications;
public function insertPublication($id, Publication $p)
{
$this->publications[$id] = $p;
}
public function fetchPublications()
{
return $this->publications;
}
}
// USAGE
$publication1 = new Book('PC', 450);
$publication2 = new Book('MEDICINA', 50);
$storage = new StorageDatabase('library.sqlite');
$debugger = DebuggerEcho::getInstance();
$library = new Library($debugger, $storage);
$library->addToLibrary($library->generateId(), $publication1);
$library->addToLibrary($library->generateId(), $publication2);
$publications = $library->getPublications();
print_r($publications);
<?php
include "1.php";
/*
Návrhový vzor Adapter přizpůsobí rozhraní určité třídy rozhraní požadovanému
klientem a umožní tak spolupráci tříd, které by kvůli nekompatibilním rozhraním
nebyly schopné spolupracovat.
Definice
---------
Návrhový vzor Adapter přizpůsobí rozhraní určité třídy rozhraní požadovanému
klientem a umožní tak spolupráci tříd, které by kvůli nekompatibilním rozhraním
nebyly schopné spolupracovat.
Pro vytvoření adaptéru, který umožní spolupráci dvou nekompatibilních rozhraní,
je nutné provést následující kroky:
1. Lokalizovat rozdíly mezi nabízeným a požadovaným rozhraním.
2. Implementovat novou třídu, která bude poskytovat požadované rozhraní.
3. Vytvořit způsob, jak předat adaptéru objekt, který má být přizpůsobený
– například pomocí principu vkládání závislostí (Dependency Injection).
4. Implementovat všechny metody vyžadované rozhraním a delegovat požadavky
dále na příslušné metody původního objektu.
5. Přihlížet k signalizování chyb.
6. V aplikaci využívat objekt adaptéru a pomocí něho „obalit“ původní objekt.
*/
class Title
{
const INFO_CATEGORY = 'category';
const INFO_PAGECOUNT = 'pageCount';
const TITLE_OPEN = 1;
const TITLE_CLOSE = 0;
protected $info = array();
protected $currentPage = 0;
protected $state = self::TITLE_CLOSE;
public function __construct($pageCount, $category)
{
$this->info[self::INFO_PAGECOUNT] = $pageCount;
$this->info[self::INFO_CATEGORY] = $category;
}
public function getInfo($info)
{
if (isset($this->info[$info])) {
return $this->info[$info];
}
}
public function setClosed($state)
{
$this->state = $state;
}
public function getClosed()
{
return $this->state;
}
public function setCurrentPage($page)
{
if (self::TITLE_CLOSE == $this->state) {
$this->setClosed(self::TITLE_OPEN);
}
$this->currentPage = $page;
}
public function getCurrentPage()
{
if (self::TITLE_CLOSE == $this->state) {
throw new ClosedException('Kniha není otevřena');
}
return $this->currentPage;
}
}
// Lisi se nazvy metod, parametry atd ...
$title = new Title(100, 'PC');
$title->setCurrentPage(47);
printf(
"Kategorie: %s\n", $title->getInfo(Title::INFO_CATEGORY)
);
printf(
"Počet stran: %d\n", $title->getInfo(Title::INFO_PAGECOUNT)
);
printf(
"Kniha je otevřena na %d. straně\n", $title->getCurrentPage()
);
$book = new Book('PC', 100);
$book->open();
$book->setPageNumber(47);
printf(
"Kategorie: %s\n", $book->getCategory()
);
printf(
"Počet stran: %d\n", $book->getPageCount()
);
printf(
"Kniha je otevřena na %d. straně\n", $book->getPageNumber()
);
// OUTPUT
/*
Kategorie: PC
Počet stran: 100
Kniha je otevřena na 47. straně
Kategorie: PC
Počet stran: 100
Kniha je otevřena na 47. straně
*/
<?php
<?php
include "1.php";
/*
Návrhový vzor Composite spojuje více objektů do stromové struktury, v níž se navenek
tváří jako jeden objekt a lze je tak i použít.
---
Spojení objektů do stromové struktury znamená následující:
1. Vytvořit možnost poskládat více objektů typu Debugger do stromové struktury.
2. Objekt, který tuto stromovou strukturu obsahuje, se musí chovat jako jeden
z objektů typu Debugger.
*/
/*
Návrhový vzor Composite spojuje více objektů do stromové struktury, v níž se navenek
tváří jako jeden objekt a lze je tak i použít.
Pro dosažení tohoto cíle je nutné provést následující kroky:
1. V případě, že tak ještě nebylo učiněné, definovat rozhraní pro samotný
objekt stromu.
2. Vytvořit novou třídu, která implementuje toto rozhraní. Do této třídy přidat
další metodu (například addChild()), které se budou předávat libovolné
objekty implementující rozhraní z bodu 1. Tyto předané objekty následně
uložit jako pole v atributu třídy.
3. Implementovat všechny metody vyžadované rozhraním z bodu 1 takovým
způsobem, že se prochází přes všechny objekty přidané do třídy v bodě 2
a postupně je na ně delegováno volání příslušné metody.
4. Vytvořit libovolné objekty a pomocí metody addChild() je přiřadit do stromové
struktury.
5. V aplikaci použít tento strom objektů místo jednotlivých objektů.
*/
class DebuggerComposite implements Debugger
{
protected $debuggers = array();
public function addDebugger(Debugger $debugger)
{
$this->debuggers[] = $debugger;
}
public function removeDebugger(Debugger $debugger)
{
$key = array_search($debugger, $this->debuggers);
if (false === $key) {
return false;
}
unset($this->debuggers[$key]);
return true;
}
public function debug($message)
{
foreach ($this->debuggers as $debugger) {
$debugger->debug($message);
}
}
}
// Jednodussi pouziti
$debuggerEcho = DebuggerEcho::getInstance();
$debuggerLog = DebuggerLog::getInstance('./library.log');
$composite = new DebuggerComposite();
$composite->addDebugger($debuggerEcho);
$composite->addDebugger($debuggerLog);
$debuggerEcho->debug('Výpis na monitor');
$debuggerLog->debug('Zápis do souboru');
$composite->debug('Monitor + Soubor');