This generator creates a cohesive 15-color design system based on HSL (Hue, Saturation, Lightness) mathematics. It ensures visual harmony by shifting all three axes simultaneously.
1. The Core Palette (100 – 500)
The main 5-color scale is your primary toolkit for any web project:
Color 100 (Lightest): Best for Section Backgrounds or Disabled Button states. Very subtle and airy.
Color 200 (Soft): Perfect for Card Backgrounds, Dividers, or Secondary Buttons.
Color 300 (Base): Your Primary Brand Color. Use this for Main Actions, Active Links, and Icons.
Color 400 (Deep): Great for Hover States on primary buttons or Subheadings.
Color 500 (Darkest): High contrast. Ideal for Main Text, Deep Borders, or Dark Mode Accents.
2. Tints & Shades (XX1 – XX9)
These are “micro-adjustments” for complex UI components like inputs or layered cards:
Tints (XX1): Derived by adding +15% Lightness. Excellent for Tooltip backgrounds or Success/Info notifications.
Shades (XX9): Derived by subtracting 15% Lightness. Use these for Inner Shadows or Pressed (Active) button states.
3. Why HSL?
Unlike HEX, HSL allows you to maintain the “energy” of a color while changing its brightness. The 8° Hue Shift applied here prevents colors from looking “muddy” or “greyish” when darkened, mimicking how real-world shadows work.
Pro Tip: Use the .gpl export to import this palette into Inkscape or GIMP to keep your design mockups and code perfectly in sync!
Написах едно тулче за калкулиране на оптимално рязане на линейни детайли. Писано е на JavaScript за браузер, защото така ми е най-бързо и удобно. При повече от 22 детайла вероятно ще започне да лагва, защото възможните комбинации стават безкрайни, а всичко го тъпча в масиви. Ако ми остане време, ще го портна до C или C#.
И един пример, как се ползва. В момента си правя стелаж за обувки и искам да знам, колко стоманени профила да си купя и как да разпределя срезовете, за да имам най-малък отпадък. Ей това е проекта:
За да разположа оптимално детайлите по профили с дължина 2 метра въвеждам парчетата в тула:
Програма за оптимизиране рязането на линейни детайли
Резултатите ми показват, че ще ми трябват общо 4 парчета метален профил, като най-големия ми остатък е 1.034m.
Тула е събран в един HTML файл. Може да се изтегли от тук: Изтегли Или да се ползва от тук: Демо
И що чак сега се сетих, че мога да ползвам SVG text като background?! И не само текст. Че даже мога да си го променям динамично през javascript! Така някои дизайни можеше да станат по-фън-шуй. По-добре късно от колкото без SVG. Едно примерче:
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction()">Try it</button>
<p style="min-height: 400px">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>
<script>
function myFunction() {
let txt = "SVG Txt";
let s = window.btoa(`
<svg height="400" width="800" xmlns="https://www.w3.org/2000/svg">
<text x="0" y="120" font-weight="bold" font-size="160" fill="#fef" stroke="#ddd">${txt}</text>
</svg>`
);
document.querySelector("p").style.background = `url('data:image/svg+xml;base64,${s}') no-repeat top left`;
}
</script>
</body>
</html>
Престои ми ремонт и имам нужда от нещо, което да ми смята бързо броя плочки или ламиниран паркет, като добавя фугите. За това си написах калкулатор на jacascript. Представлява обикновена web-страница. Във версия 002 на калкулатора са направени някои промени:
Кода е изцяло пренаписан, като вече е обектен, което ще ме улесни да прилагам нови методи на редене
Добавен е диагонален модел за редене на плочките
Добавен е генериран код за CAD-софтуера QCad
Програмата работи с всички модерни браузери и мобилни устройства. Калкулатора може да се зареди онлайн от тук: Tile Calculator
След разархивиране на архива може да се ползва само html-файла в основната директория. В папката source е развойната версия на калкулатора с scss-кода.
Кратко видео, което показва моя начин на ползване на това тулче:
Ще се опитам да опиша простичко, как се разработва прост extension add-on за Chrome. Понякога е много полезно да се работи с подобни скриптове, особено при скрапване на web-съдържание, когато конвенционалните методи не работят или изискват прекалено много усилия.
За да се създаде подобен скрипт с потребителски интерфейс ще са ни необходими няколко файла: manifest.json – всяка добавка (extension) за Chrome (а и за другите браузери) съдържа подобен скрипт, който предоставя важна информация на браузера. Повече тук: Manifest File Format popup.html – стандартно наименование на файла с потребителския интерфейс, който се появява при клик с мишката върху добавката. Разбира се, можем да създадем добавка, която няма нужда от потребителски интерфейс, но в случая аз искам да имам. Името на този файл се посочва в manifest.json. popup.js – файл, който се зарежда чрез popup.html. Можем и да нямаме подобен файл и да поместим javascript кода направо в popup.html. Но тенденциите в модерното програмиране съветват да се диференцира всичко – стилове, скриптове, html. В моя случай popup.js е двигателя на Chrome добавката. Той посочва какво, кога и къде да се активира. getPagesSource.js – файл за инжектиране в web-страницата и извлича информацията от нея. Този файл се зарежда от popup.js. icon.png – някаква иконка, която да се показва в листата с добавките на Chrome.
Нека създадем скрипт, който извлиза съдържанието на определени тагове, като използваме javascript функцията querySelectorAll(). Много приятна функция, която заменя в известна степен нуждата от XPath при web-скрапинга.
Да започваме! Първо създаваме manifest.json, като описваме какво прави тая добавка:
1
2
3
4
5
6
7
8
9
10
11
{
"name": "Simple web scraper",
"version": "1.0",
"manifest_version": 2,
"description": "Get content from tags through querySelector",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "<all_urls>"]
}
{
"name": "Simple web scraper",
"version": "1.0",
"manifest_version": 2,
"description": "Get content from tags through querySelector",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "<all_urls>"]
}
След това си правим потребителския интерфейс popup.html – бутончета, поленца, форми, стилове, каквото ни е кеф. В случая ще се огранича на минимума за моите нужди – текстово поле, бутон, слой за резултата:
chrome.runtime.onMessage.addListener(function(request, sender){
selElements(document, request.customSelector);});function selElements(document_root, s){// Tova go dobaviam zaradi kefa da polzvam foreach() v JavaScriptvar forEach =function(array, callback, scope){for(var i =0; i < array.length; i++){
callback.call(scope, i, array[i]);}};var myNodeList = document.querySelectorAll(s);var concatenateall ='';
forEach(myNodeList,function(index, value){
concatenateall = concatenateall + value.innerHTML+"<hr />";});// return concatenateall;
chrome.runtime.sendMessage({
action:"getSlectedContent",
source: concatenateall
});}
chrome.runtime.onMessage.addListener(function(request, sender) {
selElements(document, request.customSelector);
});
function selElements(document_root, s){
// Tova go dobaviam zaradi kefa da polzvam foreach() v JavaScript
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
var myNodeList = document.querySelectorAll(s);
var concatenateall = '';
forEach(myNodeList, function (index, value) {
concatenateall = concatenateall + value.innerHTML + "<hr />";
});
// return concatenateall;
chrome.runtime.sendMessage({
action: "getSlectedContent",
source: concatenateall
});
}
Това е.
Сега остава да заредим добавката в Chrome. Това става като отворим More Tools -> Extensions. След това кликаме на бутона Load unpacked и избираме директорията с файловете на нашата добавка.
На базата на тази добавка могат да се направят много други, тъй като съдържа базата за писане на добавки за Chrome.
Bootstrap и tinyMCE са ми редовна комбинация. И за да не откривам топлата вода всеки път, ще постна малко подсетки с прост мой плъгин за tinyMCE.
Важно е да се промени javascript променливата current_host. Demo Download
Един много прост пример за наследяване на клас в JavaScript.
В случая имам клас Shape (форма), който ще разширя с клас за правоъгълник (Rectangle), който на свой ред ще разширя с клас за квадрат (Square).
По-горния код е интересен, но тъй като съм го копирал и преработвал, без много да му вниквам, не е мисля, че е добър.
Ето така го оптимизирах, след като попрочетох малко за ООП-то на JavaScript:
var Shape = function () {};
var Triangle = function(w, h) { this.width = w; this.heigh = h; }
Triangle.prototype = new Shape();
Triangle.prototype.getArea = function () {return this.width * this.heigh; };
// ====== Kvadrat
var Square = function (l) { this.width = l; this.heigh = l; };
Square.prototype = new Triangle();
// ======== Examples
var square = new Square(4),
triangle = new Triangle(2, 5);
print(square.getArea());
print(triangle.getArea());
За да стартирам кода използвам SublimeText2 с инсталирана приставка за стартиране на команди от шела Turtlestein, а за JavaScript интерпретатор използвам SpiderMonkey 1.8.5 for Windows.
Прост, базов RTF редактор за сайт
Дълго съм се чудил кой е най-подходящия JavaScript Wysiwyg редактор с най-много възможности за напасване към сайт. Ползвал съм NicEdit, TinyMCE и други, които сам съм писал, неподдържащи rich text format (RTF). Обаче напасването на тези редактори към различни дизайни е развибащо от към бачкане и тестване в различните браузери. Реших да почопля няколко такива редактора и да разбера кое е толкова загадъчно и сложно, за да се напише подобен редактор. Истината е тривиална и се казва – iFrame. Този таг се ползва в почти всички подобни редактори, точно заради поддръжката му на RTF. При събмитване на формата, цялото съдържание на iform се подава на textarea, който си седи удобно скрит.
Това е моят редактор, без CSS-форматиране, като в примера добавям и опция за обработка на текста от базата данни, където присъства без тагове, с ексейпнати малко по-рискови символи.
<?php$field='<a href="aloooha">Test\'ed. kavicha</a> dyra, byra.<br />Още текст и още "кирилица".';$clearpost=$field;if(isset($_POST['button'])){echo$_POST['myTextArea'];$clearpost=$_POST['myTextArea'];}//$clearpost = preg_replace('@delete|select|insert|update|where@i',"", $clearpost); // Почистване на //$clearpost = preg_replace('/[\x7f-\xff]/', "", $clearpost); // Clear Dirty Data$clearpost=preg_replace("/;/",";",$clearpost);$clearpost=preg_replace("/\*/","*",$clearpost);$clearpost=preg_replace("/\r\n/","<br />",$clearpost);$clearpost=preg_replace("/\r/","<br />",$clearpost);$clearpost=preg_replace("/\n/","<br />",$clearpost);$clearpost=preg_replace("/</","<",$clearpost);$clearpost=preg_replace("/=/","=",$clearpost);$clearpost=preg_replace("/>/",">",$clearpost);$clearpost=preg_replace("/\'/","'",$clearpost);$clearpost=preg_replace("/\`/","`",$clearpost);$clearpost=preg_replace("/\"/",""",$clearpost);if(!get_magic_quotes_gpc())$clearpost=preg_replace('@\\\@',"\",$clearpost);else{$clearpost=stripslashes($clearpost);$clearpost=preg_replace('@\\\@',"\",$clearpost);}$clearpost=preg_replace("/'/","\'",$clearpost);// Ескейпване на единичната кавичка, за да може да се показва в iframe!!!?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251" />
<script src="wiswyg_ned/nedEditor.js"></script>
<script type="text/javascript">
window.onload=function(){
iFrameOn();
if(isIE){
var myFrame = document.getElementById('richTextField');
var frameDoc = myFrame.contentDocument || myFrame.contentWindow;
if (frameDoc.document){
frameDoc = frameDoc.document;
}
frameDoc.write ('<?phpechohtml_entity_decode($clearpost,ENT_QUOTES);?>') ;
} else {
window.frames['richTextField'].document.body.innerHTML = '<?phpechohtml_entity_decode($clearpost,ENT_QUOTES);?>' ;
}
}
</script>
</head>
<!-- <body onLoad="iFrameOn();" > -->
<body>
<form action="" enctype="multipart/form-data" name="myForm" id="myform" method="post">
<div id="wysiwyg_cp" style="padding:8px; width:700px;">
<input type="button" onClick="iBold()" value="B">
<input type="button" onClick="iUnderline()" value="U">
<input type="button" onClick="iItalic()" value="I">
<input type="button" onClick="iFontSize()" value="Text Size">
<input type="button" onClick="iForeColor()" value="Text Color">
<input type="button" onClick="iHorizontalRule()" value="HR">
<input type="button" onClick="iUnorderedList()" value="UL"><br />
<input type="button" onClick="iOrderedList()" value="OL">
<input type="button" onClick="iLink()" value="Link">
<input type="button" onClick="iUnLink()" value="UnLink">
<input type="button" onClick="iImage()" value="Image">
<input type="button" onClick="iRemoveFormat()" value="Remove Format">
</div>
<!-- Hide(but keep)your normal textarea and place in the iFrame replacement for it -->
<textarea style="display:none;" name="myTextArea" id="myTextArea" cols="100" rows="14"></textarea>
<iframe name="richTextField" id="richTextField" ></iframe>
<br />
<input type="submit" name="button" id="button" value="Make Changes" onClick="javascript:submit_form();"/>
</form>
</body>
</html>
// Check Browservar isOpera =!!(window.opera&& window.opera.version);// Opera 8.0+var isFirefox = testCSS('MozBoxSizing');// FF 0.8+var isSafari =Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')>0;// At least Safari 3+: "[object HTMLElementConstructor]"var isChrome =!isSafari && testCSS('WebkitTransform');// Chrome 1+var isIE =/*@cc_on!@*/false|| testCSS('msTransform');// At least IE6function testCSS(prop){return prop in document.documentElement.style;}//====================function iFrameOn(){
richTextField.document.designMode='On';//window.frames['richTextField'].document.body.innerHTML = '<a href="aloooha">Aloha</a> dyra, byra.<br />Още текст има тук.'; }function iRemoveFormat(){
richTextField.document.execCommand('removeformat',false,null);}function iBold(){
richTextField.document.execCommand('bold',false,null);}function iUnderline(){
richTextField.document.execCommand('underline',false,null);}function iItalic(){
richTextField.document.execCommand('italic',false,null);}function iFontSize(){var size = prompt('Enter a size 1 - 7','');
richTextField.document.execCommand('FontSize',false,size);}function iForeColor(){var color = prompt('Define a basic color or apply a hexadecimal color code for advanced colors:','');
richTextField.document.execCommand('ForeColor',false,color);}function iHorizontalRule(){
richTextField.document.execCommand('inserthorizontalrule',false,null);}function iUnorderedList(){
richTextField.document.execCommand("InsertOrderedList",false,"newOL");}function iOrderedList(){
richTextField.document.execCommand("InsertUnorderedList",false,"newUL");}function iLink(){var linkURL = prompt("Enter the URL for this link:","http://");
richTextField.document.execCommand("CreateLink",false, linkURL);}function iUnLink(){
richTextField.document.execCommand("Unlink",false,null);}function iImage(){var imgSrc = prompt('Enter image location','');if(imgSrc !=null){
richTextField.document.execCommand('insertimage',false, imgSrc);}}function submit_form(){var theForm = document.getElementById("myform");
theForm.elements["myTextArea"].value= window.frames['richTextField'].document.body.innerHTML;
theForm.submit();}
// Check Browser
var isOpera = !!(window.opera && window.opera.version); // Opera 8.0+
var isFirefox = testCSS('MozBoxSizing'); // FF 0.8+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
// At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !isSafari && testCSS('WebkitTransform'); // Chrome 1+
var isIE = /*@cc_on!@*/false || testCSS('msTransform'); // At least IE6
function testCSS(prop) {
return prop in document.documentElement.style;
}
//====================
function iFrameOn(){
richTextField.document.designMode = 'On';
//window.frames['richTextField'].document.body.innerHTML = '<a href="aloooha">Aloha</a> dyra, byra.<br />Още текст има тук.';
}
function iRemoveFormat(){
richTextField.document.execCommand('removeformat',false,null);
}
function iBold(){
richTextField.document.execCommand('bold',false,null);
}
function iUnderline(){
richTextField.document.execCommand('underline',false,null);
}
function iItalic(){
richTextField.document.execCommand('italic',false,null);
}
function iFontSize(){
var size = prompt('Enter a size 1 - 7', '');
richTextField.document.execCommand('FontSize',false,size);
}
function iForeColor(){
var color = prompt('Define a basic color or apply a hexadecimal color code for advanced colors:', '');
richTextField.document.execCommand('ForeColor',false,color);
}
function iHorizontalRule(){
richTextField.document.execCommand('inserthorizontalrule',false,null);
}
function iUnorderedList(){
richTextField.document.execCommand("InsertOrderedList", false,"newOL");
}
function iOrderedList(){
richTextField.document.execCommand("InsertUnorderedList", false,"newUL");
}
function iLink(){
var linkURL = prompt("Enter the URL for this link:", "http://");
richTextField.document.execCommand("CreateLink", false, linkURL);
}
function iUnLink(){
richTextField.document.execCommand("Unlink", false, null);
}
function iImage(){
var imgSrc = prompt('Enter image location', '');
if(imgSrc != null){
richTextField.document.execCommand('insertimage', false, imgSrc);
}
}
function submit_form(){
var theForm = document.getElementById("myform");
theForm.elements["myTextArea"].value = window.frames['richTextField'].document.body.innerHTML;
theForm.submit();
}
Написах скромен HTML-JavaScript калкулатор за пресмятане на прости рецепти за сокчета (e-juice) за електронни цигари. Демо на калкулатора. Изтегляне.
Share and Enjoy !
Shares
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.AcceptRead More
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.