MS SQL OFFSET FETCH

Воспользовавшись предложением offset fetch (аналог mysql-го limit-a) для пагинации, наткнулся на проблемку, при переходе между страницами запрос выдавал тот же результат. В запросе всегда присутствует сортировка по одному из столбцов.
select rr.[rank] r, * v.*, otfile
, try_convert(date, col12, 104) col12D, convert(varchar(10), try_convert(date, col12, 104), 104) col12DH, ceiling((count(*) over())/10.0) pagesTotal from m_dev v
 inner join (select * from (values('4370'),('4371'),('4372'),('4374'),('3461'),('3462'),('3464'),('3465'))t(code)) codes on (v.col10 like codes.code + '%')
 inner join containstable (m_dev, col99, '("трансформатор" or "трансформатор*") and ("тока" or "тока*") and ("италия" or "италия*")', language 1049) rr on (v.id = rr.[key])
 where v.deleted is null 
 order by r
 offset 20 rows fetch next 10 rows only
Грешил на использование полнотекстового поиска, и объединение с результатами функции CONTAINSTABLE, провел эксперименты над данными попроще.
select t1.id1 id1, t1.id2+t2.id2-10 id2 from 
(select * from (values(1,10),(1,20),(1,30),(1,40),(1,50),(1,60),(1,70),(1,80),(1,90)) t (id1, id2)) t1
 cross join (select * from (values(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)) t (id1, id2)) t2
 order by id1
 offset 0 rows fetch next 10 rows only
;

select t1.id1 id1, t1.id2+t2.id2-10 id2 from 
(select * from (values(1,10),(1,20),(1,30),(1,40),(1,50),(1,60),(1,70),(1,80),(1,90)) t (id1, id2)) t1
 cross join (select * from (values(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)) t (id1, id2)) t2
 order by id1
 offset 10 rows fetch next 10 rows only
;

select t1.id1+t2.id1-1 id1, t1.id2+t2.id2-10 id2 from 
(select * from (values(1,10),(1,20),(1,30),(1,40),(1,50),(1,60),(1,70),(1,80),(1,90)) t (id1, id2)) t1
 cross join (select * from (values(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)) t (id1, id2)) t2
 order by id1
 offset 0 rows fetch next 10 rows only
;

select t1.id1+t2.id1-1 id1, t1.id2+t2.id2-10 id2 from 
(select * from (values(1,10),(1,20),(1,30),(1,40),(1,50),(1,60),(1,70),(1,80),(1,90)) t (id1, id2)) t1
 cross join (select * from (values(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)) t (id1, id2)) t2
 order by id1
 offset 10 rows fetch next 10 rows only
;
Получил результаты, соответственно для каждого запроса, появились косяки.
id1	id2		id1	id2		id1	id2		id1	id2
1	1		1	12		1	12		1	12
1	2		1	13		1	11		1	11
1	3		1	14		1	9		1	9
1	4		1	15		1	8		1	8
1	5		1	16		1	7		1	7
1	6		1	17		1	6		1	6
1	7		1	18		1	5		1	5
1	8		1	19		1	4		1	4
1	9		1	21		1	3		1	3
1	11		1	22		1	2		1	2
В плане выполнения появилась сортировка. План выполнения Итого, решаем проблему всегда добавляя последней сортировку по уникальному столбцу. Если его нет, генерим, как в примере. Если есть, как в моем рабочем запросе, в нем я просто добавил
order by r, v.id
select t1.id1+t2.id1-1 id1, t1.id2+t2.id2-10 id2, row_number() over (order by (select 1)) rn from 
(select * from (values(1,10),(1,20),(1,30),(1,40),(1,50),(1,60),(1,70),(1,80),(1,90)) t (id1, id2)) t1
 cross join (select * from (values(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)) t (id1, id2)) t2
 order by id1, rn
 offset 0 rows fetch next 10 rows only
;

select t1.id1+t2.id1-1 id1, t1.id2+t2.id2-10 id2, row_number() over (order by (select 1)) rn from 
(select * from (values(1,10),(1,20),(1,30),(1,40),(1,50),(1,60),(1,70),(1,80),(1,90)) t (id1, id2)) t1
 cross join (select * from (values(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)) t (id1, id2)) t2
 order by id1, rn
 offset 10 rows fetch next 10 rows only
;

id1	id2	rn		id1	id2	rn
1	1	1		1	12	11
1	2	2		1	13	12
1	3	3		1	14	13
1	4	4		1	15	14
1	5	5		1	16	15
1	6	6		1	17	16
1	7	7		1	18	17
1	8	8		1	19	18
1	9	9		1	21	19
1	11	10		1	22	20

Excel RegExp Match

Функцию в модуль
Public Function regMatch(ByVal inStr2 As String, ByVal patternStr As String, Optional ByVal idx As Integer = -1) As String
Dim regEx As New RegExp
Dim regMatches As Object
    With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = patternStr
            
            If .Test(inStr2) Then
                If (idx >= 0) Then
                    If .Execute(inStr2)(0).SubMatches.Count() > idx Then
                    regMatch = .Execute(inStr2)(0).SubMatches(idx)
                    Else
                    regMatch = ""
                    End If
                Else
                    regMatch = .Execute(inStr2)(0)
                End If
            Else
                regMatch = ""
            End If
        
    End With
End Function
Пример формулы в ячейке
=regMatch(H3;"(\(|\{)\s*([0-9A-Z]{8}\s*\-\s*[0-9A-Z]{8})\s*(\}|\))";1)
Последний параметр необязательный
=regMatch(H4;"(\(|\{)\s*([0-9A-Z]{8}\s*\-\s*[0-9A-Z]{8})\s*(\}|\))")

Fly to cart

«Полет в корзину», если у нас нужно «отправлять в полет» только картинку, то все очень легко, пример с перемещением всей карточки и текст описания и картинка. Безымянный15 Свойство zoom не использую, ибо при его использовании расчет координат отличается от браузера к браузеру, использую transform: scale, если не поддерживается, просто «сворачиваю» по высоте.
Ниже код того что на картинке. <style> .card { font-size: 60px; color: #444; } .card .panel-body { font-size: 60px; } .card .fa-cart-plus { font-size: 26px; } .cart { margin: 60px 100px; } .cart i { font-size: 46px; color: #aeb733; } .card-body { position: relative; margin-bottom: 6px; } .card-body-copy { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1100; zoom: 1; } </style> <div id="cart" class="cart clearfix"> <button type="button" class="btn btn-default btn-lg pull-right"><i class="fa fa-shopping-cart" aria-hidden="true"></i></button> </div> <div class="row"> <div class="col-xs-3"> <div class="card panel panel-default"> <div class="panel-heading clearfix"> <div class="pull-right"><h4>Card 1</h4></div> </div> <div class="panel-body"> <div class="card-body"> <img src="/public/img/export_excel2.png"> 111<i style="color: #ee0;" class="fa fa-bitcoin" aria-hidden="true"></i> </div> <div class="clearfix"> <div class="pull-right"><button class="btn"><i class="fa fa-cart-plus" aria-hidden="true"></i></button></div> </div> </div> </div> </div> <div class="col-xs-3"> <div class="card panel panel-default"> <div class="panel-heading clearfix"> <div class="pull-right"><h4>Card 2</h4></div> </div> <div class="panel-body"> <div class="card-body"> <img src="/public/img/export_excel2.png"> 222<i style="color: #c0e;" class="fa fa-eur" aria-hidden="true"></i> </div> <div class="clearfix"> <div class="pull-right"><button class="btn"><i class="fa fa-cart-plus" aria-hidden="true"></i></button></div> </div> </div> </div> </div> <div class="col-xs-3"> <div class="card panel panel-default"> <div class="panel-heading clearfix"> <div class="pull-right"><h4>Card 3</h4></div> </div> <div class="panel-body"> <div class="card-body"> <img src="/public/img/export_excel2.png"> 333<i style="color: #0f0;" class="fa fa-dollar" aria-hidden="true"></i> </div> <div class="clearfix"> <div class="pull-right"><button class="btn"><i class="fa fa-cart-plus" aria-hidden="true"></i></button></div> </div> </div> </div> </div> </div> <script type="text/javascript"> (function($) { $('body').on('click', '.btn', function(e) { var card = $(this).closest('.panel-body').find('.card-body'); if (!card.size()) return; var cardCopy = $(this).closest('.panel-body').find('.card-body-copy'); if (!cardCopy.size()) $('<div/>').addClass('card-body-copy').html( card.html() ).appendTo(card); var cart = $('#cart .fa-shopping-cart'); var cardCopy = $(this).closest('.panel-body').find('.card-body-copy'); if (!cardCopy.size() || !cart.size()) return; var cardCoord = cardCopy.offset(); var cartCoord = cart.offset(); var lenght = Math.sqrt(Math.pow((cardCoord.top-cartCoord.top),2) + Math.pow((cardCoord.left-cartCoord.left),2)); var zoom = 0.5; var speed = 1/4; // pixel in msec var maybeTransform = (card.get(0).style['transform'] !== undefined); var l = (cartCoord.left - cardCoord.left); var t = (cartCoord.top - cardCoord.top); $(cardCopy).animate($.extend({ opacity: 0.4, left: (l > 0 ? '+' : '') + l.toString(), top: (t > 0 ? '+' : '') + t.toString(), }, maybeTransform ? {} : {height: 'toggle'}), { duration: lenght/speed, step:function(now, fx){ if (fx.prop == 'left') { $(this).css('transform-origin', '0 0' ); $(this).css('transform', 'scale('+ (zoom+(1-zoom)*(1-now/l)) +')' ); } }, complete:function(){ $(this).remove(); // cart.toggle( "bounce", { times: 3 }, "slow" ); } }); }); })(jQuery); </script>

API Вконтакте «Поделиться» и параметр noparse, не работает, решено.

Решил поделиться проблемой и решением, небольшим костылем, может кто набредет.
Возникла необходимость добавить к статье виджет Вконтакте «Поделиться», покурил документацию, все сделал как там написано, в моем варианте решил воспользоваться параметром noparse и указать параметры публикации
<script type="text/javascript">
document.write(VK.Share.button({
  url: 'http://mysite.com',
  title: 'Заголовок страницы',
  image: 'http://mysite.com/mypic.jpg',
  noparse: true
}));
</script>
Но не тут то было, все параметры брались со страницы, noparse игнорировался. Хм.

Перекопал гуглем весь инет, и безрезультатно, да многие пишут об этой проблеме, и на этом все. Рабочее решение попадалось, добавить все параметры в урл, не стал даже рассматривать, да оно работает, но урл то немножко другой, ну и ведь в документации, в документации написано, это же не забор.

Решил посмотреть устройство vk.com/js/api/share.js и что же там отправляется при клике на кнопку.

Параметры отправлялись, все честно, постом, НО, РЕДИРЕКТ (302), и все параметров больше нет, вот почему работал вариант с дописыванием параметров в урл. Редирект выполняется для смены протокола на https, у тех у кого сайт работает через https изначально никаких проблем нет.
Безымянный12 Для остальных простое решение, после инициализации первой кнопки добавляем такой код, 
VK.Share._base_domain = 'https:' + VK.Share._base_domain;
усе, теперь форма будет отправляться на https и редиректа не будет.

Полный пример рабочего кода:
!function (d, id, pr1, pr2) {
  var js = d.createElement("script");
  js.src = "http://vk.com/js/api/share.js?90";
  js.onload = js.onreadystatechange = function () {
  if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") {
    if (!this.executed) {
      this.executed = true;
      setTimeout(function () {
        d.getElementById(id).innerHTML = VK.Share.button(pr1, pr2); 
        VK.Share._base_domain = 'https:' + VK.Share._base_domain;
      }, 0);
    }
  }};
  d.documentElement.appendChild(js);
}(document,"vk",{
  url: document.URL,
  title: 'Заголовок страницы',
  description: 'Описание ...',
  image: 'http://mysite.com/mypic.jpg',
  noparse: true,
},{type: 'round', text: 'Поделиться',});

JavaScript генератор паролей

Простой модулек для генерации пароля с настройкой обязательного наличия заглавных, цифр, символов и настройкой набора символов исключений.

reverse string search in Excel?

В Excel отсутствует функция поиска вхождения при чтении справа налево(обратного поиска). Воспользуемся VBA, создадим обертку к уже существующей в VBA функции и будем использовать ее непосредственно в формулах ячейки. Заходим в среду VBA (ALT+F11), добавляем модуль, в него вставляем функцию
Public Function ПОИСКОБР( _
   ByVal StringCheck As String, _
   ByVal StringMatch As String, _
   Optional ByVal Start As Integer = -1 _
) As Integer

    ПОИСКОБР = InStrRev(StringCheck, StringMatch, Start)
    
End Function
Все, используем ее в формулах книги.

UNPIVOT просто все столбцы в строчки

select * from
  (select * from (values(0,1,1,1,4), (5,6,6,6,9)) t (id1, id2, id3, id4, id5))t
   unpivot (value for columnName in (id1, id2, id3, id4, id5)) ttt
value	columnName
0	id1
1	id2
1	id3
1	id4
4	id5
5	id1
6	id2
6	id3
6	id4
9	id5

IE and cursor and pseudo element, detect click event on pseudo-element

Отображаем курсор над псевдо элементом, как обычно у всех, все хорошо, в ИЕ не работает.
IE :-(
IE :-)
Для ИЕ используем пустой спан как контейнер.
<div id="test1" class="test">IE -(</div>
<div id="test2" class="test">IE -)<span></span></div>
И уже на него
#test2 span {
 cursor: pointer;
}
Ну и тут же тема, как ловить события от псевдоэлемента, имеем три варианта:
1) воспользуемся CSS свойством pointer-events, но тут ограничение, поддержка только в современных браузерах, так и сделано для первого примера
2) обернуть реальным элементом, тема для второго варианта
3) еще можно контролировать координаты точки клика, как-то так
if (e.offsetX > e.target.clientWidth) {

text-overflow: ellipsis и иже сним

Забью свой костыль в виде аналога эффекта получаемого с помощью свойства text-overflow: ellipsis.
В моем случае задача немного сложнее, текст не умещался совсем не много, не больше чем на 50%, потому нужно было его отобразить при наведении курсора.
Все очень легко, на помощь пришли, псевдокласс :hover и свойство direction: rtl. Все бы ничего, Firefox, Chrome, Opera, все отлично, IE приплыли.
Безымянный Ну раз уж, придется задействовать JavaScript, значит чуточку добавим требований, текст не будет просто переключаться с отображения, то с начала, то с конца, пусть он плавно прокручивается, тут и ограничение в 50% снимется.
Сляпал плагин, малютка, меньше сотни строк.

А как работает твой браузер?
Раз, два, три, четыре, пять, вышел зайчик погулять, заинька вышел… Вдруг охотник выбегает, прямо в зайчика стреляет, пиф-паф, ой-ой-ой, умирает зайчик мой, привезли его домой, оказался он живой
Живой пример
Раз, два, три, четыре, пять, вышел зайчик погулять, заинька вышел… Вдруг охотник выбегает, прямо в зайчика стреляет, пиф-паф, ой-ой-ой, умирает зайчик мой, привезли его домой, оказался он живой
Есть нюанс в зависимости от шрифта могут «уехать» точки, нужно добавить некую поправку, но пока править не стал, в моем случае все и так работало.