GyverPortal

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@Старик Похабыч, описать может и правильно описал.
но есть же еще и input[type=\"number\"] возможно он главнее, чем .mini

так и есть, удалил основной, оставил свой и все работает...
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,253
1,297
Москва
нет, если используется class , то ищется соотв. тип в css
Пример:
Кусок CSS:
Код:
td{
width: 50%;
background-color:lightgray;     
border: 3px;
}
.main_td{ 
    border: 3px;
    border-style: groove;
    border-top-style: none;
    border-radius:0 0 20px 20px;
}
.active_td{ 
    width: 50%;
    border: 3px;
    border-style: groove;
    border-bottom-style: none;
    border-radius:20px 20px 0 0;
}
.noactive_td{       
    background-color:gray;
    border: 3px;
    border-style: none;
    border-bottom-style: inset;
    border-radius: 20px 20px 0px -0px;
}
Кусок html:
<tr>
<td class="noactive_td"><center><a style="color: white;" href="base_page.html">Настройки<a></center></td>
<td class="active_td"><center><a href="net_page.html">Сеть</center><a></td>
</tr>
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@Старик Похабыч, проверил код страницы, стиль мой встает, если удалить стиль заводской, то мой применяется, если и заводской и мой, то стиль в код встает, но не применяется. Ширина страницы прикрепляется от заводского.
mini.JPG
если в редакторе вручную отключить в input, то ширина меняется
 
Изменено:

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@Олег Поляков, завтра попробую)
По идее должно работать, должен повысить приоритет, как и писал в #57.
Проверил с телефона, через режим разработчика, вписал это слово.
Всё сработало, значит и в прошивке должно сработать. Блок прописан для двух полей, третье заводское)
IMG_20220520_004533.jpg
CSS:
".mini150 {max-width:150px !important;}\n"
Тогда можно наделать несколько вариантов с шагом 50. Или как-то вынести в код, если html примет этот вариант.
 
Изменено:

aidar_i

✩✩✩✩✩✩✩
1 Май 2021
64
8
Тогда можно наделать несколько вариантов с шагом 50. Или как-то вынести в код, если html примет этот вариант.
Да так придется, получается аналогично изменению цвета.
А вывод картинок работает отлично. Где берете пиктограммы? Или рисуете? Я вот нарисовал.
Вывод картинок.png
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@aidar_i, иконки в интернете, есть сайты с иконками, например icons8.ru
Забей в поиск, найдутся несколько)
 
  • Лойс +1
Реакции: aidar_i

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Добавил новый элемент, теперь можно задать ширину числового поля ввода, в GyverPortal.h добавить в компоненты
C++:
       void NUMBER_MINI(int width, const char* name, const char* place, int value = INT32_MAX) {
        *_gp_sptr += F("<input class=\"mini");
        *_gp_sptr += width;
        *_gp_sptr += F("\" type=\"number\" name=\"");
        *_gp_sptr += name;
        *_gp_sptr += F("\" id=\"");
        *_gp_sptr += name;
        if (value != INT32_MAX) {
            *_gp_sptr += F("\" value=\"");
            *_gp_sptr += value;
        }
        *_gp_sptr += F("\" placeholder=\"");
        *_gp_sptr += place;
        *_gp_sptr += F("\" onchange=\"GP_click(this)\">\n");     
    }
Формат записи изменен!!!
C++:
add.NUMBER_MINI(width, "", "", "");
width задается фиксировано: 50,100,150,200,250,300
если хотите задать свои значения, добавьте аналогично в код темы, как указано ниже)
добавить в themes.h
CSS:
".mini50 {max-width:50px!important;}\n"
".mini100 {max-width:100px!important;}\n"
".mini150 {max-width:150px!important;}\n"
".mini200 {max-width:200px!important;}\n"
".mini250 {max-width:250px!important;}\n"
".mini300 {max-width:300px!important;}\n"
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Добавил новый элемент, теперь можно задать ширину текстового поля ввода, в GyverPortal.h добавить в компоненты
C++:
    void TEXT_MINI(int width, const char* name, const char* place, const char* value = "") {
        *_gp_sptr += F("<input class=\"mini");
        *_gp_sptr += width;
        *_gp_sptr += F("\" type=\"text\" name=\"");
        *_gp_sptr += name;
        *_gp_sptr += F("\" id=\"");
        *_gp_sptr += name;
        *_gp_sptr += F("\" value=\"");
        *_gp_sptr += value;
        *_gp_sptr += F("\" placeholder=\"");
        *_gp_sptr += place;
        *_gp_sptr += F("\" onchange=\"GP_click(this)\">\n");
    }

    void TEXT_MINI(int width, const char* name, const char* place, String& value) {
        TEXT_MINI(width, name, place, (const char*)value.c_str());
    }
    void TEXT_MINI(int width, const char* name, const char* place, char* value) {
        TEXT_MINI(width, name, place, (const char*)value);
    }
и для float в значении
C++:
        void NUMBER_MINI(int width, const char* name, const char* place, float value) {
        *_gp_sptr += F("<input class=\"mini");
        *_gp_sptr += width;
        *_gp_sptr += F("\" type=\"number\" name=\"");
        *_gp_sptr += name;
        *_gp_sptr += F("\" id=\"");
        *_gp_sptr += name;       
        *_gp_sptr += F("\" value=\"");
        *_gp_sptr += value;       
        *_gp_sptr += F("\" placeholder=\"");
        *_gp_sptr += place;
        *_gp_sptr += F("\" onchange=\"GP_click(this)\">\n");     
    }
формат записи аналогичен предыдущему сообщению.
вносить ничего в файл темы не нужно, если внесено в предыдущем сообщении.

п.с. теперь надо подумать над стилизацией, чтобы можно было выравнивать по левому краю, а не все по центру)

@Старик Похабыч, вот теперь по вашему профилю)
что нужно изменить в коде css или html чтобы каждый элемент можно было задать как по центру, так и по левому краю на примере этой страницы?)
далее будем думать, как применить это в библиотеке)
HTML:
<!DOCTYPE HTML><html><head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"></head><body>
<script>function GP_click(arg){var xhttp=new XMLHttpRequest();var v;
if(arg.type=="checkbox")v=arg.checked?'1':'0';
else v=arg.value;
if(v.charAt(0)=='#')v=v.substring(1);
xhttp.open("POST","GP_click?"+arg.name+"="+v,true);xhttp.send();}
function GP_clickid(btn,tar){var xhttp=new XMLHttpRequest();
xhttp.open("POST","GP_click?"+btn+"="+document.getElementById(tar).value,true);xhttp.send();
}</script>
<div align="center" style="margin:auto;max-width:1000px;">
<style type="text/css">
body {font-family: sans-serif;margin-top:15px;}
hr {width:95%;margin-bottom:10px;max-width:400px;}
h2 {margin:8px 0;}
span {font-size:20px;}
label {font-size:20px;margin:0 5px;}
.chartBlock {border-radius:15px;margin:10px;width:90%;max-width:1000px;height:500px}
.block {border-radius:10px;border:1px solid #394048;background-color:#f2f2f2;padding:0px;margin-top:3px;margin-bottom:15px;width:90%;max-width:400px;}
.blockHeader {font-size:20px;color:#222222;border-radius:10px 10px 0px 0px;border-bottom:1px solid #394048;background-color:#c2c2c2;padding:4px 0px;margin:0px;margin-bottom:8px;width:100%;}
.sldBlock{width:90%;display:flex;flex-direction:row;justify-content:right;align-items:center}.sldLbl{font-size:15px;}.sldLblValue{font-size:20px;padding:8px;border-radius:10px;}
.mini50 {max-width:50px!important;}
.mini100 {max-width:100px!important;}
.mini150 {max-width:150px!important;}
.mini200 {max-width:200px!important;}
.mini250 {max-width:250px!important;}
.mini300 {max-width:300px!important;}
input[type="number"],input[type="text"],input[type="password"],input[type="date"],input[type="time"],input[type="range"],input[type="color"],input[type="checkbox"],select,textarea
{border-radius:8px;max-width:350px;padding:3px 10px;vertical-align:middle;position:relative;margin:2px 0 7px 0;font-size:20px;height:40px;cursor:pointer;}
input[type="range"] {width:60%;height:30px;padding:0px;}
input[type="date"],input[type="time"] {width:180px;}
input[type="color"] {width:100px;height:40px;}
input[type="checkbox"] {width:27px;height:27px;margin-bottom:10px;}
input[type="number"],input[type="text"],input[type="password"],select,textarea {display:inline-block;border:1px solid #ccc;border-radius:8px;box-sizing:border-box;cursor:auto;}
input[type="submit"],input[type="button"] {max-width:350px;height:60px;font-size:28px;width:90%;margin:8px 5px;background-color:#4CAF50;border:none;border-radius:8px;color:white;cursor:pointer;padding:0px 10px;}
input[type=submit],input[type="button"]:hover {background-color:#45a049;}
textarea {width: 100%;}.led {margin:20px 18px;}
.led:after {width:25px;height:25px;border-radius:25px;top:-10px;left:-9px;position:relative;content:'';display:inline-block;border:2px solid;border-color:#858585;background-color:#323232}
.led:checked:after {box-shadow:0px 0px 10px;}
.led.red:checked:after {border-color:red !important;color:red !important;background-color:red !important;}
.led.green:checked:after {border-color:lime !important;color:lime !important;background-color:lime !important;}
.miniButton{height:40px !important;font-size:20px!important;width:auto!important;}
.switch{margin:10px 0 5px;position:relative;display:inline-block;width:60px;height:34px}
.switch input{opacity:0;width:0;height:0}
.slider{border-radius:34px;position:absolute;cursor:pointer;top:-5px;left:0;right:0;bottom:5px;background-color:#ccc;-webkit-transition:.1s;transition:.1s}
.slider:before{border-radius:50%;position:absolute;content:"";height:26px;width:26px;left:4px;bottom:4px;background-color:#fff;-webkit-transition:.1s;transition:.1s}
input:checked+.slider{background-color:#2196f3}
input:checked+.slider:before{-webkit-transform:translateX(26px);-ms-transform:translateX(26px);transform:translateX(26px)}
</style>
<h2 id="">Настройки сервиса</h2>
<h2 id="">Народный мониторинг</h2>
<div class="block" id="blockBack">
<form action="/save_monitoring" method="POST">
<input type="checkbox" name="Monitoring" id="Monitoring" onclick="GP_click(this)">
<label id="">Включить мониторинг</label>
</div>
<div class="block" id="blockBack">
<div class="blockHeader">Интервал отправки, в сек</div>
<input type="number" name="delay_narod" id="delay_narod" value="600" placeholder="" onchange="GP_click(this)">
<br>
<label id="">не менее 300! если нет поддержки</label>
<br>
<label id="">сервиса мониторинга</label>
</div>
<div class="block" id="blockBack">
<div class="blockHeader">Включить отправку показаний датчиков</div>
<label class="switch"><input type="checkbox" name="nm_sens_tempH" id="nm_sens_tempH" onclick="GP_click(this)">
<span class="slider"></span></label><label id="">Комнатная температура</label>
<br>
<label class="switch"><input type="checkbox" name="nm_sens_tempS" id="nm_sens_tempS" onclick="GP_click(this)">
<span class="slider"></span></label><label id="">Уличная температура</label>
<br>
<label class="switch"><input type="checkbox" name="nm_sens_pres" id="nm_sens_pres" onclick="GP_click(this)">
<span class="slider"></span></label><label id="">Давление</label>
</div>
<input type="submit" value="Сохранить">
</form>
<form action="/index" method="POST">
<input type="submit" value="На главную">
</form>
</div></body></html>
 
Изменено:
  • Лойс +1
Реакции: aidar_i

aidar_i

✩✩✩✩✩✩✩
1 Май 2021
64
8
ОК, сделаю.
Мне кажется, не нужно отдельно создавать функцию
NUMBER_MINI, просто изменить NUMBER
C++:
   void NUMBER(int width,const char* name, const char* place, int value = INT32_MAX) {
        *_gp_sptr += F("<input class=\"_width");
        *_gp_sptr += width;
        *_gp_sptr += F("\"type=\"number\" name=\"");
        *_gp_sptr += name;
        *_gp_sptr += F("\" id=\"");
        *_gp_sptr += name;
        if (value != INT32_MAX) {
            *_gp_sptr += F("\" value=\"");
            *_gp_sptr += value;
        }
        *_gp_sptr += F("\" placeholder=\"");
        *_gp_sptr += place;
        *_gp_sptr += F("\" onchange=\"GP_click(this)\">\n");   
    
    }


"._width50 {max-width:50px!important;}\n"
"._width100 {max-width:100px!important;}\n"
"._width150 {max-width:150px!important;}\n"
"._width200 {max-width:200px!important;}\n"
"._width250 {max-width:250px!important;}\n"
"._width300 {max-width:300px!important;}\n"
"._width320 {max-width:350px!important;}\n"
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@aidar_i, да я думал сначала, что оставить всё в Number... Но, сделал отдельной, чтобы не путаться и не путать других...) Если Алекс внедрит в общий вариант, не против)

если сделать ограничение поле ввода, то надо снова обращаться к css, т.к. html не принимает атрибут maxlength.
тут уже упираемся в движок, или только делать под себя, добавляя свои стили...
походу аналогично и с предыдущей идеей, выравнивание по левому краю и по центру...
 
Изменено:
  • Лойс +1
Реакции: Олег Поляков

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
Ребят, вот эта бяка откуда всплывает?)
IMG_20220521_213250.jpg
в коде нет ничего)
C++:
        void NUMBER_MINI(int width, const char* name, const char* place, float value) {
        *_gp_sptr += F("<input class=\"mini");
        *_gp_sptr += width;
        *_gp_sptr += F("\" type=\"number\" name=\"");
        *_gp_sptr += name;
        *_gp_sptr += F("\" id=\"");
        *_gp_sptr += name;  
        *_gp_sptr += F("\" value=\"");
        *_gp_sptr += value;  
        *_gp_sptr += F("\" placeholder=\"");
        *_gp_sptr += place;
        *_gp_sptr += F("\" onchange=\"GP_click(this)\">\n");
    }
C++:
float coef = 0.4;
add.NUMBER_MINI(100, "coef", "", coef);
может тут?)
C++:
    void AJAX_CLICK() {
        *_gp_sptr += F("<script>function GP_click(arg){var xhttp=new XMLHttpRequest();var v;\n"
        "if(arg.type==\"checkbox\")v=arg.checked?'1':'0';\nelse v=arg.value;\n"
        "if(v.charAt(0)=='#')v=v.substring(1);\n"
        "xhttp.open(\"POST\",\"GP_click?\"+arg.name+\"=\"+v,true);xhttp.send();}\n"
        "function GP_clickid(btn,tar){var xhttp=new XMLHttpRequest();\n"
        "xhttp.open(\"POST\",\"GP_click?\"+btn+\"=\"+document.getElementById(tar).value,true);xhttp.send();\n}"
        "</script>\n");
    }
найден баг, внутри portal.form() вызов portal.attachBuild() работает, а внутри portal.click() не работает...
 

aidar_i

✩✩✩✩✩✩✩
1 Май 2021
64
8
Все таки решил делать через клас, как рекомендовал Олег. Создал классы на разные свойства компонентов и вставляя их через пробелы можно менять различные свойства компонентов (цвет фона и шрифта, высоту и ширину компонента и шрифта, выравнивание компонента....)
 
Изменено:
  • Лойс +1
Реакции: Олег Поляков

Олег Поляков

★★★✩✩✩✩
18 Янв 2022
105
112
www.1812.ru
@aidar_i, вот! Через css можно все оформления, отступы и выравнивания гораздо гибче сделать, не модифицируя отдельные функции отображения элементов, не вводя новые параметры в эти функции. class в css, слава природе, позволяет указывать через пробел любое разумное количество css-классов для html-элементов.
 

vitek1658

✩✩✩✩✩✩✩
27 Май 2022
5
0
Добрый день! Сделал простенький код по изменению яркости светодиода, но сколько не нажимай в браузере кнопку прибавления яркости, счетчик так и остается на первом значении. На обычной ардуине с мех кнопками всё работает (пример из статьи про eeprom). Плата esp8266 npdemcu.
C++:
#include <GyverPortal.h>
const char* ssid     = "ESP32-Access-Point";
const char* password = "1234567890";
#define LED_PIN 2       // пин светодиода
int LEDbright = 0;

void build() {
  String b;
  BUILD_BEGIN(b);
  add.THEME(GP_LIGHT);
  add.AJAX_UPDATE("lbl");
  add.TITLE("Изменение яркости");
  add.HR();
  add.LABEL(LEDbright, "lbl"); add.LABEL("%"); add.BREAK();
  add.BUTTON_MINI("btnm", "  -  "); add.BUTTON_MINI("btnp", " + "); add.BREAK();
  BUILD_END();
  }
GyverPortal portal;

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход
  // запускаем точку доступа
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  portal.start(WIFI_AP);
     portal.attachBuild(build);
  portal.list.init(1);
  portal.list.add(&LEDbright, "lbl", T_INT);
 
 
}
void loop() {
 portal.tick();
  // опрос кнопок
  if (portal.click("btnp")) {
   // увеличение по клику
    LEDbright += 5;
    Serial.println("LedUp");
    setBright();
  }
  if (portal.click("btnm")) {
     // уменьшение по клику
    LEDbright -= 5;
    Serial.println("LedDown");
    setBright();
  }
   if (portal.update()) {
  if (portal.update("lbl")) portal.answer(LEDbright);
 
}
}
void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
  Serial.println(LEDbright);
}
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
setup:
        server.on("/update", HTTP_POST, []() {
        server.sendHeader("Connection", "close");
        server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
        ESP.restart();
      }, []() {
        HTTPUpload& upload = server.upload();
        if (upload.status == UPLOAD_FILE_START) {
          Serial.setDebugOutput(true);
          WiFiUDP::stopAll();
          Serial.printf("Update: %s\n", upload.filename.c_str());
          uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
          if (!Update.begin(maxSketchSpace)) { //start with max available size
            Update.printError(Serial);
          }
        } else if (upload.status == UPLOAD_FILE_WRITE) {
          if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
            Update.printError(Serial);
          }
        } else if (upload.status == UPLOAD_FILE_END) {
          if (Update.end(true)) { //true to set the size to the current progress
            Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
          } else {
            Update.printError(Serial);
          }
          Serial.setDebugOutput(false);
        }
        yield();
              server.begin();
        MDNS.addService("http", "tcp", 80);
      });
Страница с выбором файла:
  BUILD_BEGIN(b_f);
  *_gp_sptr += F("<form action=\"update\"");
  *_gp_sptr += F("enctype=\"multipart/form-data\"");
  *_gp_sptr += F("method=\"POST\">\n");
  *_gp_sptr += F("<label for=\"file\">Обновление прошивки</label><br><br>\n");
  *_gp_sptr += F("<input type=\"file\" name=\"update\">\n");
  *_gp_sptr += F("<input type=\"submit\" value=\"Обновить прошивку\"");
  *_gp_sptr += F("onclick=\"update\">\n");
  *_gp_sptr += F("</form>\n");
  BUILD_END();
Переход на эту страницу работает, а вот как заставить код на этой странице сработать для обновления прошивки, непонятно, есть мысли?)
Код страницы в браузере
HTML:
<!DOCTYPE HTML><html><head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"></head><body>
<script>function GP_click(arg){var xhttp=new XMLHttpRequest();var v;
if(arg.type=="checkbox")v=arg.checked?'1':'0';
else v=arg.value;
if(v.charAt(0)=='#')v=v.substring(1);
xhttp.open("POST","GP_click?"+arg.name+"="+v,true);xhttp.send();}
function GP_clickid(btn,tar){var xhttp=new XMLHttpRequest();
xhttp.open("POST","GP_click?"+btn+"="+document.getElementById(tar).value,true);xhttp.send();}</script>
<div align="center" style="margin:auto;max-width:1000px;">
<form action="update"enctype="multipart/form-data"method="POST">
<label for="file">Обновление прошивки</label><br><br>
<input type="file" name="update">
<input type="submit" value="Обновить прошивку"onclick="update">
</form></div></body></html>
 

Олег Поляков

★★★✩✩✩✩
18 Янв 2022
105
112
www.1812.ru
@aidar_i, сам по себе элемент какой-то недоделанный. Одни браузеры, например Yandex под Андроидом, отображают текущее значение ползунка, а Safari под iOS - не отображает. А шаманить и делать костыли на javascript'е очень бы не хотелось.
 

aidar_i

✩✩✩✩✩✩✩
1 Май 2021
64
8
@Олег Поляков, Спсибо, решил так:
заменил в GyverPortal.h в функции void SLIDER(const char* name, int value, int min, int max, int step = 1) onchange на oninput .
C++:
       //Модифицировано
        *_gp_sptr += F("\" oninput=\"GP_click(this);document.getElementById('");
        *_gp_sptr += name;
        *_gp_sptr += F("_value').innerHTML=this.value;\">\n");
       //Конец модификации
 
  • Лойс +1
Реакции: Олег Поляков