• Как найти циклы в массиве?

    @ksnk
    Вот более оптимизированный говнокод ;)
    $array = [
        385 => 392,
        386 => 392,
        387 => 392,
        390 => 402,
        402 => 421,
        405 => 401,
        409 => 416,
        410 => 401,
        414 => 402,
        416 => 389,
        420 => 421,
        421 => 422,
        422 => 420,
    ];
    
    foreach ($array as $key => $value) {
        $level=0;
        $leaf=[$key=>$level]; $v=$value;
        while(true){
            if(!isset($array[$v])) break;
            $v=$array[$v];
            if(isset($leaf[$v])) {
                // loop found
                // is it real loop ?
                if($key==$v) {
                    printf("\n %s => %s", $key, $value);
                }
                break;
            }
            $leaf[$v]=++$level;
        }
    }
    Ответ написан
    2 комментария
  • Как создать элементы пагинации с многоточием?

    @ksnk
    Надо исправить ошибки.
    Их много. Например свойство pagination определено 2 раза.
    Но это не так страшно, javascrpt игнорирует ненужное,
    type: 'custom', нужно определить в секции pagination, чтобы вообще вызывался собственный рендеринг, вот тогда обнаружится еще одна -
    const end = current + 1;
            if (current < 2) {
              end += 2 - current;
            }
    Присвоение константе - этого JS уже не прощает...
    Дальше уже нужно править стили...
    Ответ написан
  • Как сделать отступ от текста JS+HTML?

    @ksnk
    Тег < tt> -отображение текста моноширинным шрифтом, обрамить им нужный div, или вообще подменить его на тот тег
    Ну и выводить числа с ведущими пробелами:
    function TableYchastki() {
            let n = ChisloYchastkov.value, h=1+Math.floor(Math.log10(n));
            div1.style.display = "block";
            for (let i = 1; i <= n; i++) {
              div1.innerHTML = div1.innerHTML + "Площадь повреждённой территории на " +
                 (" ".repeat(h) + i).slice (-h).replace(/\s/g,"&nbsp;") + 
                 " участке: <input type=text id='ploshad" + i + "'><br>";
            }
        }

    Ответ написан
  • Как получить пользовательское название поля типа crm_status?

    @ksnk
    Примерно так
    $list=CRest::call("crm.status.list",
                [
                    'order'=>['SORT'=>'ASC'],
                    'filter'=>["ENTITY_ID"=>'INDUSTRY']
                ]
            );

    Выглядит примерно так:
    Array
    (
        [result] => Array
            (
                [0] => Array
                    (
                        [ID] => 69
                        [ENTITY_ID] => INDUSTRY
                        [STATUS_ID] => IT
                        [NAME] => Сельское хозяйство
                        [NAME_INIT] => 
                        [SORT] => 10
                        [SYSTEM] => N
                        [CATEGORY_ID] => 
                        [COLOR] => 
                        [SEMANTICS] => 
                    )
    
                [1] => Array
                    (
                        [ID] => 71
                        [ENTITY_ID] => INDUSTRY
                        [STATUS_ID] => TELECOM
                        [NAME] => Добывающая
                        [NAME_INIT] => 
                        [SORT] => 20
                        [SYSTEM] => N
                        [CATEGORY_ID] => 
                        [COLOR] => 
                        [SEMANTICS] => 
                    )
    ...
    Ответ написан
    1 комментарий
  • Любой символ в маске ввода номера, как сделать?

    @ksnk
    В этой самой маске столько косяков и мелей, что сразу может и крыша поехать. У меня сейчас вот такое чудище стоит
    $("input[type='tel']").each(function(){
                    if(!this.inputmask) { // ставили уже ?
                        let mask="+7 (999) 999-99-99[999]"; // 6 - 3-я 9-ка, 9-4-z 9-rf, 10-5.
                        function oninput(){
                            const wphoneValue = jQuery(this).val().replace(/\D/g, '');
    
                            if (wphoneValue.length >= 4) {
                                const firstThreeDigits = parseInt(wphoneValue.substring(1, 4));
                                if(firstThreeDigits>699 && firstThreeDigits<900 && firstThreeDigits!==812){
                                    // remove first letter from value
                                    jQuery(this).val(jQuery(this).val().replace(/\+7 \([78]/,'+7 ('));
                                    let pos=0;
                                    for(let x=wphoneValue.length;x>1;x--){
                                        pos=mask.indexOf('9', pos+1);
                                    }
                                    this.setSelectionRange && this.setSelectionRange(pos,pos,"forward");
                                }
                            }
                        }
                        $(this).on('input', oninput)
                            .inputmask({
                            "mask": mask,
                            skipOptionalPartCharacter: " ",
                            placeholder: "_",
                            autoclear: false,
                            onBeforePaste: function (pastedValue, opts) {
                                pastedValue = pastedValue.toLowerCase().replace(/\D/g, '').replace(/7(\d{10})/, '$1').replace(/8(\d{10})/, '$1');
                                return pastedValue;
                            }
                        })
                        var that=this;
                        setTimeout(function(){oninput.call(that)},10);
                    }
                })

    Пояснения:
    • input[type='tel'] - < input type="tel" ... вместо text позволит автоматически использовать мобильным броузерам телефоны и вставлять кнопки "позвонить". Это удобно. Да и вдруг еще где приспичит маску телефона поставить...
    • В хвосте маски вставлены еще возможные цифры, это про запас... Вдруг кто-то вставит код не для России, будет обидно потерять последние цифры вместе с клиентом. Хотя это, наверное, рудимент для таких случаев. Такие номера все равно придется вручную проверять, если клиента потерять таки действительно жалко.
    • onBeforePaste предназначена для Cut&paste в маску всяких красиво отформатированных телефонов, со скобками и дефисами в странных местах, возможно, с ведущей восьмеркой.
    • oninput позволяет избежать потери последней цифры, если юзер начал набивать номер, клавишами, начиная с 8-ки. Ввод корректируется сам, выкидывая ведущую 8, если он не напоминает код города 812... В соответствии с маской функция выкидывает лишнее и вставляет нужное.
    • Вызов функции oninput по таймауту позволяет бороться с автозаполнением номеров телефонов, которые броузер запомнил не так, как требуется странице.
    Ответ написан
    Комментировать
  • Как стилизовать данную фигуру?

    @ksnk
    Рисуешь то, что тебе нравится в редакторе, например здесь https://yqnn.github.io/svg-path-editor/
    потом получившийся path вставляешь в clip-path
    Как-нибудь так

    Тут проблема в том, что закругления будут делаться не совсем окружностями, и нужна точность в проведении линий. Но редактор довольно удобен для рисования всяких разных фигур.
    Ответ написан
    Комментировать
  • Как добавить "уголки" правильно?

    @ksnk
    Можно поизвращатся.
    Вставить элемент с нужными границами и вырезать из него все ненужное
    Ну или даже одним элементом
    Ответ написан
    Комментировать
  • Как правильно обновить БД с помощью формы выведенной в цикле?

    @ksnk
    В комментариях советовали посылать одной формой, нужно только копировать шаблон ввода одного персонажа. Примерно так
    Основной смысл - шаблоном будут поля ввода первого участника, после копировании шаблона нужно подменить все атрибуты name новых элементов, добавив +1 в индекс имен.
    На стороне php просто пробежаться по массивам name, lastname и age и раскидать кого куда надо.
    Ответ написан
    Комментировать
  • Как реализовать анимацию линии?

    @ksnk

    Например вот так.
    Из минусов - при изменениии размера экрана рисование линий начинается заново. Но, возможно, это и плюс.
    В любом случае - для рисования и несложной анимации канвасом тут есть почти все необходимые запчасти
    Ответ написан
  • Как трансформировать код из 1 вида в другой?

    @ksnk
    Отредактировал немного, сейчас работает лучше, но в принципе - наверное лучше в класс перетащить, а то 3 анонимные функции как-то криво начинают выглядеть.
    <?php
    
    $source = <<<'code'
    <?php
    
    $name = 'anon';
    echo '<h2>';
    echo 'Number is: ';
    echo count(["1","2","3"]);
    echo '</h2>';
    echo 'CHECK
    
    ';
    echo 1 + 3 . '-'. 4 . '=' . 0;
    echo '
    
    ';
    echo '<h2>';
    echo 'Olololo';
    echo '</h2>';
    echo '
    
    ';
    echo '<h3>';
    echo 'QWErty';
    echo '</h3>';
    echo '
    
    
    ';
    echo '<h2>';
    echo 'Hello, ';
    echo $name;
    echo '</h2>';
    echo '
    
    ';
    foreach ([1,2,3] as $item) {
    echo '
        ';
    echo '<h2>';
    echo 'Number is: ';
    echo $item;
    echo '</h2>';
    echo '
    ';
    }
    code;
    
    $tokens = token_get_all($source);
    $last_token=false;
    
    $getnext=function() use (&$tokens, &$last_token){
      $token=array_shift($tokens);
      if(is_null($token)) return false;
      if(is_array($token)){
        $last_token= token_name($token[0]);
        return  $token[1];
      } else {
        $last_token='';
          return  $token;
      }
    };
    
    $getbracket=function($bracket) use (&$tokens,$getnext,&$last_token){
    	$stack=[]; $buf=$bracket;
    	
    	if($bracket=='[') array_unshift($stack,']');
    	if($bracket=='(') array_unshift($stack,')');
    	while(false!==($x=$getnext())){
    		$buf.=$x;
    		if($x==$stack[0]){
    			array_shift($stack);
    			if(count($stack)==0) break;
    		}
    		if($x=='(') array_unshift($stack,')');
    		if($x=='{') array_unshift($stack,'}');
    		if($x=='[') array_unshift($stack,']');
    	}
    	return $buf;
    };
    
    $getecho=function() use (&$tokens,$getnext,$getbracket,&$last_token){
      $buf='';
      $buf2='';
      $waitecho=false;
      while(false!==($x=$getnext())){
      	//echo '{'.$last_token.' '.$x.'}';
        if($last_token==='' && $x==';'){
          $waitecho=true;
          $buf2.=$x;
        } elseif($last_token==='T_ECHO' && $waitecho){ // склеиваем
          $waitecho=false;
          $buf.=',';$buf2='';
        } elseif($last_token==='T_WHITESPACE' && $waitecho){ 
          $buf2.=$x;
        } else if($waitecho){
          return $buf.$buf2.$x;
        } else if($last_token==='T_CONSTANT_ENCAPSED_STRING') {// склеиваем константные строки с одинаковыми кавычками
          $s=$x[0];
          $y = preg_replace('~'.preg_quote($s,"~'").'\s*[\.\,]\s*$~', '', $buf, 1, $count);
          if($count>0)
             $buf=$y.substr($x,1);
          else
            $buf.=$x;
        } else if($last_token==='' && in_array($x,['[','('])) {
        	$buf.=$getbracket($x);
        } else {
          $buf.=$x;
        }
      };
      return '';
    };
    
    while(false!==($x=$getnext())) {
      echo $x;
      if($last_token=='T_ECHO'){
        echo $getecho();
      }
    }
    ?>


    <?php
    
    $name = 'anon';
    echo '<h2>Number is: ', count(["1","2","3"]), '</h2>CHECK
    
    ', 1 + 3 . '-'. 4 . '=' . 0, '
    
    <h2>Olololo</h2>
    
    <h3>QWErty</h3>
    
    
    <h2>Hello, ', $name, '</h2>
    
    ';
    foreach ([1,2,3] as $item) {
    echo '
        <h2>Number is: ', $item, '</h2>
    ';
    }
    Ответ написан
  • Как правильно сверстать такую границу у блока?

    @ksnk
    Немного переработал вариант от Ильи Бондаренко, зато с прозрачностью и котиками
    Ответ написан
    Комментировать
  • Как нарисовать тонкую нормальную линию на канвасе между двумя кликами мыши?

    @ksnk
    У канваса есть еще атрибуты - высота и ширина. По этим атрибутам и идет рисование и их нужно установить для корректного пересчета координат рисования в клики.
    const rect = $canvas.getBoundingClientRect(); // после этого вставить 2 строки
        $($canvas).attr('width', rect.width);
        $($canvas).attr('height', rect.height);
    //...

    получится что-то вроде https://codepen.io/ksnk/pen/LYMPbxZ
    Ответ написан
    1 комментарий
  • Как сверстать блок с такой же линией?

    @ksnk
    В общем случае сложно обойтись без скрипта. Можно рисовать линии канвасом, например так.
    Ответ написан
    1 комментарий
  • Как сделать так, чтобы при наведении на блок появлялся список и не исчезал, пока не уберешь со списка курсор?

    @ksnk
    Вообще-то удобнее для отвечающего и быстрее для спрашивающего смастерить пример, например на codepen.io . Например так

    В отличии от кода в вопросе используются методы mouseenter, mouseleave как более подходящие к месту и toggle заменен на явную установку-выкидывание класса.
    Ответ написан
    Комментировать
  • Как в css сделать так чтоб текст был всегда прижат к низу, не зависимо тайтл с переносом или нет?

    @ksnk
    Надо на верстку смотреть, но обычно - заголовку блока задают либо фиксированный размер+overflow:hidden, либо min-height. К примеру 2.5em (подбирается по месту, чтобы влезало точное количество строк). В этом случае в заголовок будет помещаться 2 строки текста. и все описания, расположенные ниже, окажутся на одной высоте. Если min-height задать, то очень большой заголовок не будет обрезан, а поместится полностью, но именно этот блок окажется сдвинут. Останется только вручную посмотреть что не влезло и поменять заголовки, или оставить так...
    Ответ написан
    Комментировать
  • Как выделить строку в таблице?

    @ksnk
    Лучше на JS добавлять класс элементу TR и от него плясать с раскраской. Но можно пользоваться псевдоэлементом has, он уже почти везде есть...
    https://codepen.io/ksnk/pen/dygbmWL
    Ответ написан
  • Как сделать авторизацию по ссылке для фида?

    @ksnk
    Вот упрощенный пример. Пароль-пользователь указан в файле. Каталог для выгрузки файлов - там же.

    <?php
    
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
        header('WWW-Authenticate: Basic realm="My Realm"');
        header('HTTP/1.0 401 Unauthorized');
        echo 'Authentification required.';
        exit;
    } else {
        // config!
        $password='test';
        $user='test';
        $upload_dir=$_SERVER['DOCUMENT_ROOT'].'/tmp/';
        //
    
        if($_SERVER['PHP_AUTH_USER']!=$user ||$_SERVER['PHP_AUTH_USER']!=$password){
            echo 'No user found, sorry.';
            exit;
        }
    
        $filename=$_SERVER['QUERY_STRING'];
        if(!is_readable($upload_dir.$filename)){
            echo 'No file found, sorry.';
            exit;
        }
    
        header('Content-type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($upload_dir.$filename));
        readfile($upload_dir.$filename);
    }

    Использование

    https://test:test@site/file.php?filetoupload.txt
    Ответ написан
    Комментировать
  • Строка из БД как условие сравнения в if?

    @ksnk
    У меня где-то использовался `язык фильтров` - строка с условиями, которую удобно вписывать в область фильтра в столбик таблицы с данными. Постим на сервер - получаем фильтрованное.
    Сама строка условий выглядит примерно так
    count=2,<2;count=3,<300,>44
    условия соединяются запятой, по AND, точкой с запятой - по OR, у OR более низкий приоритет. Операция сравнения соединяет 2 операнда, если один из операндов пустой - берется "сравниваемое значение", если число - то число, иначе ищем во внешних "данных".
    Если записать строку на php - будет что-то вроде
    $current=45; // значение, которое сравниваем
    $data=['count'=>3]; // внешние данные
    if( ($data['count']==2 && $current<2) || ($data['count']==3 &&$current>44 && $current<300)){
        // ...
    }

    Удобно в языке то, что парсер его компактен и легко допиливается напильником по месту.
    function evaluate($current,$cond,$data=[]){
        $res=false;
        foreach(explode(';',$cond) as $or){ //or
            foreach(explode(',',$or) as $and) { //and
                if(preg_match('/^(.*?)(<=|>=|<|>|=)(.*?)$/',$and,$m)){
                    $a=trim($m[1]);$b=trim($m[3]);
                    if(empty($a)) $a=$current;
                    else if(is_numeric($a)) $a=0+$a;
                    else if(isset($data[$a])) $a=$data[$a];
                    else {
                        $res=false; break;
                    }
                    if(empty($b)) $b=$current;
                    else if(is_numeric($b)) $b=0+$b;
                    else if(isset($data[$b])) $b=$data[$b];
                    else {
                        $res=false; break;
                    }
                    if($m[2]=='<=') $res=$a<=$b;
                    else if($m[2]=='>=') $res=$a>=$b;
                    else if($m[2]=='>') $res=$a>$b;
                    else if($m[2]=='<') $res=$a<$b;
                    else if($m[2]=='=') $res=$a==$b;
                } else {
                    $res=false;
                    //throw new \Exception('Некорректное условие в строке '.$and)
                }
                if(!$res) break; // выход по AND
            }
            if($res) break; // выход по OR
        }
        return $res;
    }
    
    $data=['count'=>3];
    
    var_dump(true===evaluate(45,'count=2,<2;count=3,<300,>44', $data));
    var_dump(true===evaluate(1,'<2'));
    var_dump(true===evaluate(1,'>3;<2,>1;<2'));
    Ответ написан
    1 комментарий
  • Как валидировать кнопку у формы при незаполненном инпуте?

    @ksnk
    Так ?
    Кнопка отправки формы - одна - Next
    При нажатии на "Ввод" внутри текстового инпута происходит сабмит формы, При этом срабатывает самая первая кнопка сабмит, которая попадется в форме. Так что порядок кнопок немного другой, а чтобы визуально не отличалось - передернуто с помощью float:left .
    Ну и обрабатывать форму должен сервер, так что все набранные данные туда и отправляем....
    Ответ написан