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

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

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

Use jQuery .on and hover

метод hover() и псевдособытие «hover» разные вещи, тем более, что hover event support in On() was deprecated in jQuery 1.8, and removed in jQuery 1.9

используем два события mouseenter и mouseleave, в таком кратком виде

jQuery(function($) {
    // имитируем подгрузку аяксом
    $('#test').append( Array(6).join('<div></div>') );

    $('#test').on({
      mouseenter: function () {
        $(this).text( $(this).index() + 1 );
      },
      mouseleave: function () {
        setTimeout( $.proxy( function(){$(this).text('')}, this ), 350 );
      }
    }, 'div');
}(jQuery));

Simple filter table jQuery plugin

Понадобился простой фильтр в табличке по значениям с «памятью» все сессий, сваял jQuery плагин с хранением данных в локальном хранилище (localStorage).
NИДМЭСДоговорКварталКомментарийСостояние
1 58 МЭС Центра 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
2 57 МЭС Северо-Запада 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
3 56 МЭС Волги 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
4 55 МЭС Урала 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
5 54 МЭС Западной Сибири 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
6 53 МЭС Сибири 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
7 52 МЭС Востока 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
8 51 МЭС Центра 30-2012 от 18.10.2012 III 2016 Формирование
9 50 МЭС Северо-Запада 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
10 49 МЭС Волги 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
11 48 МЭС Востока 30-2012 от 18.10.2012 IV 2016 Октябрь 2016 Утвержден
12 47 МЭС Урала 30-2012 от 18.10.2012 IV 2016 Октябрь 2016 Утвержден
13 46 МЭС Западной Сибири 30-2012 от 18.10.2012 IV 2016 Октябрь 2016 Утвержден
14 45 МЭС Востока 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
15 44 МЭС Урала 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
16 43 МЭС Западной Сибири 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
17 42 МЭС Центра 30-2012 от 18.10.2012 IV 2016 Перенос на октябрь Утвержден
18 41 МЭС Сибири 30-2012 от 18.10.2012 IV 2016 Перенос на октябрь Утвержден
19 40 МЭС Центра 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
20 39 МЭС Северо-Запада 30-2012 от 18.10.2012 IV 2016 Перенос на октябрь Утвержден
21 38 МЭС Центра 30-2012 от 18.10.2012 III 2016 Утвержден
22 37 МЭС Юга 30-2012 от 18.10.2012 IV 2016 Декабрь 2016 Формирование
23 36 МЭС Волги 30-2012 от 18.10.2012 IV 2016 Перенос на октябрь Утвержден
24 35 МЭС Урала 30-2012 от 18.10.2012 III 2016 Утвержден
25 34 МЭС Западной Сибири 30-2012 от 18.10.2012 III 2016 Утвержден
26 33 МЭС Сибири 30-2012 от 18.10.2012 III 2016 Утвержден
27 32 МЭС Сибири 30-2012 от 18.10.2012 IV 2015 Не подлежит закрытию Формирование
28 31 МЭС Востока 30-2012 от 18.10.2012 III 2016 Утвержден
29 26 МЭС Урала 30-2012 от 18.10.2012 II 2016 Утвержден
30 25 МЭС Волги 30-2012 от 18.10.2012 II 2016 Утвержден
31 24 МЭС Северо-Запада 30-2012 от 18.10.2012 II 2016 Утвержден
32 22 МЭС Западной Сибири 30-2012 от 18.10.2012 II 2016 Утвержден
33 21 МЭС Сибири 30-2012 от 18.10.2012 II 2016 Утвержден
34 20 МЭС Юга 30-2012 от 18.10.2012 II 2016 Утвержден
35 19 МЭС Центра 30-2012 от 18.10.2012 II 2016 Утвержден

HTML5 data-* attributes and jQuery.data() in examples

HTML5 data-* attributes and jQuery.data() в примерах:
1) загруженная страница содержит

<input id="test" type="text" data-data1="qwer" data-data2-test="asdf" value="test">


2) на Vanilla JS
document.getElementById("test").dataset.data1
"qwer"
document.getElementById("test").dataset.data2-test
NaN
document.getElementById("test").dataset.data2Test
"asdf"

-- для IE 10- dataset не доступен

>> document.getElementById("test").dataset.data1 
"Не удалось получить свойство "data1" ссылки, значение которой не определено или является NULL" 
>> document.getElementById("test").getAttribute("data-data1") 
"qwer" 
>> document.getElementById("test").getAttribute("data-data2-test") 
"asdf" 
используем jQuery для чтения, все универсально, и главное, в IE тоже работает как надо
$('#test').data('data1')
"qwer"
$('#test').data('data2-test')
"asdf"
$('#test').data('data2Test')
"asdf"
а сейчас попробуем сохранить данные используя jQuery.data(), и более того сохраним объект содержащий функцию
видим результат, с помощью jQuery можем легко воспользоваться сохраненным объектом
но эти данные не появляются в dataset, они сохраняются в кэше jQuery, при первой же попытке получить значение data элемента, jQuery создаст свойство в DOM структуре этого элемента «jQuery + $.now()» и присвоит ему уникальный идентификатор (или ранее), который и будет использоваться как ключ для доступа к кэшу, а так же, скопирует атрибуты data в свой кэш.
$('#test').data('data3', {tt: 10, fn1: function(n){ return this.tt * n + n } })

$('#test').data('data3').fn1(5)
55
document.getElementById("test").dataset.data3
undefined
jQuery1113024019371896630481: 63

jQuery.cache[63]
Object {data: Object, parsedAttrs: true}
jQuery.cache[63].data
Object {data2Test: "asdf", data1: "qwer", data3: Object}
$('#test').data()
Object {data2Test: "asdf", data1: "qwer"}
$.cache[63].data
Object {data2Test: "asdf", data1: "qwer"}
$('#test').attr('data-data1', 'qazwsx')
[<input id=​"test" type=​"text" data-data1=​"qazwsx" data-data2-test=​"asdf" value=​"test">​]
$('#test').data()
Object {data2Test: "asdf", data1: "qwer"}
$('#test')[0].dataset
DOMStringMap {data1: "qazwsx", data2Test: "asdf"}
$('#test').attr('data-data3', 'qazwsx')
[<input id=​"test" type=​"text" data-data1=​"qazwsx" data-data2-test=​"asdf" value=​"test" data-data3=​"qazwsx">​]
$('#test')[0].dataset
DOMStringMap {data1: "qazwsx", data2Test: "asdf", data3: "qazwsx"}
$('#test').data()
Object {data2Test: "asdf", data1: "qwer"}
$('#test').data('data1', 123)
[<input id=​"test" type=​"text" data-data1=​"qazwsx" data-data2-test=​"asdf" value=​"test" data-data3=​"qazwsx">​]
$('#test').data()
Object {data2Test: "asdf", data1: 123}
$('#test')[0].dataset
DOMStringMap {data1: "qazwsx", data2Test: "asdf", data3: "qazwsx"}
$('#test')[0].dataset.data1 = 777
777
$('#test')[0].dataset
DOMStringMap {data1: "777", data2Test: "asdf", data3: "qazwsx"}
$('#test').data()
Object {data2Test: "asdf", data1: 123}
Итоги:
  1. data атрибуты загружаются в свойство attributes элемента
  2. если браузер поддерживает DOMStringMap, то в свойство dataset дублируются все атрибуты data? имена приводятся в верблюжью нотацию, если в имени присутствуют «-«
  3. jQuery сохраняет копию data атрибутов и более их не обновляет, ни в одну из сторон, jQuery использует javascript для хранения данных, а не DOM, вот тут то плагины jQuery и хранят свои экземпляры

Change the color of address bar in mobile Chrome for Android browser

Зададим цвет адресной строки для Chrome под Android на примере WordPress.
В файл схемы …./header.php в тег добавим <meta name="theme-color" content="#ff66ee"> и увидим такой результат Screenshot_2016-08-30-20-44-13_com.android.chrome

Select a particular option in a SELECT element in jQuery

Выбрать элемент списка с помощью jQuery, столько разных усложнений, а ведь на то она и библиотека, чтобы сделать код проще.
$("#selId").val‌​("val1").cha‌​nge();
-- или если с мультивыбором
$("#selId").val‌​(["val3", "val5"]).cha‌​nge();
а можно и всяко разно
$('#selId option[value="val1"]').‌​attr('selected', 'selected');
$('#selId option').filter(function(i, o) { return $(o).val() == "val1"})
по этому поводу часто идут холивары, но можно заглянуть в код jQuery и увидеть что присвоение значения списку установит свойство selected = true для элемента списка с равным значением.
jQuery.fn.extend({
	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[0];
......................
		return this.each(function( i ) {
			var val;

......................
			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		});
......................
jQuery.extend({
	valHooks: {
		option: {
			get: function( elem ) {
				var val = jQuery.find.attr( elem, "value" );
				return val != null ?
					val :
					// Support: IE10-11+
					// option.text throws exceptions (#14686, #14858)
					jQuery.trim( jQuery.text( elem ) );
			}
		},
		select: {
			get: function( elem ) {
				var value, option,
					options = elem.options,
					index = elem.selectedIndex,
					one = elem.type === "select-one" || index < 0,
					values = one ? null : [],
					max = one ? index + 1 : options.length,
					i = index < 0 ?
						max :
						one ? index : 0;

				// Loop through all the selected options
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// oldIE doesn't update selected after form reset (#2551)
					if ( ( option.selected || i === index ) &&
							// Don't return options that are disabled or in a disabled optgroup
							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				return values;
			},

			set: function( elem, value ) {
				var optionSet, option,
					options = elem.options,
					values = jQuery.makeArray( value ),
					i = options.length;

				while ( i-- ) {
					option = options[ i ];

					if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {

						// Support: IE6
						// When new option element is added to select box we need to
						// force reflow of newly added node in order to workaround delay
						// of initialization properties
						try {
							option.selected = optionSet = true;

						} catch ( _ ) {

							// Will be executed only in IE6
							option.scrollHeight;
						}

					} else {
						option.selected = false;
					}
				}

				// Force browsers to behave consistently when non-matching value is set
				if ( !optionSet ) {
					elem.selectedIndex = -1;
				}

				return options;
			}

......................

Difference between decodeURIComponent and decodeURI

Различия в decodeURI и decodeURIComponent, в последнем нет исключений он декодирует все символы.
tt1 = encodeURI(" ; / ? : @ & = + $ , # ")
"%20;%20/%20?%20:%20@%20&%20=%20+%20$%20,%20#%20"
tt2 = encodeURIComponent(" ; / ? : @ & = + $ , # ")
"%20%3B%20%2F%20%3F%20%3A%20%40%20%26%20%3D%20%2B%20%24%20%2C%20%23%20"
tt3 = decodeURI(tt1)
" ; / ? : @ & = + $ , # "
tt4 = decodeURI(tt2)
" %3B %2F %3F %3A %40 %26 %3D %2B %24 %2C %23 "
tt5 = decodeURIComponent(tt1)
" ; / ? : @ & = + $ , # "
tt6 = decodeURIComponent(tt2)
" ; / ? : @ & = + $ , # "
const jschar js_uriReservedPlusPound_ucstr[] =
    {';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#', 0};

static JSBool
str_decodeURI(JSContext *cx, uintN argc, jsval *vp) {
    JSString *str;

    str = ArgToRootedString(cx, argc, vp, 0);
    if (!str)
        return JS_FALSE;
    return Decode(cx, str, js_uriReservedPlusPound_ucstr, vp);
}

static JSBool
str_decodeURI_Component(JSContext *cx, uintN argc, jsval *vp) {
    JSString *str;

    str = ArgToRootedString(cx, argc, vp, 0);
    if (!str)
        return JS_FALSE;
    return Decode(cx, str, js_empty_ucstr, vp);
}

Web Worker многопоточность в JavaScript

Рассчитаем число Pi в 5000 знаков воспользовавшись Web Worker, setTimeout, и без использования разбора очереди setTimeout или многопоточности(Multithreading) Web Worker, цикл в основном (и единственном) потоке JavaScript. Сравним время выполнения, ощущения по блокировки графического интерфейса (UI). Воспользуемся формулой Джона Мачайна John Machin
π=16arctan(15)4arctan(1239)
arctanx=xx33+x55x77+x99
Web WorkersetInterval(0) (на каждую итерацию)цикл while
Pi
Код под капотом.
Мои итоги, плюс Web Worker? работа в отдельном потоке, никакого влияния на основной поток, отсутствие задержки setTimeout, на каждый вызов порядка 10мс, и это если в это время очередь не занята еще чем-либо, например, визуальными эффектами jQuery, да и при setTimeout приходится модифицировать код задачи, итерации делить по вызовам setTimeout. Минус, хотя это и не минус, по другому быть и не может, отсутствие доступа к не потокобезопасным ресурсам DOM, window, document, parent. Где же использовать практически, однооконные веб-приложения с некими относительно тяжелыми расчетами, мне решать такую задачу пока не приходилось.
И еще, FF тормоз, см. скрин, все три теста на одной машинке.

Варианты тестов на разных браузерах и машинках. Google Chrome Internet Explorer Mozila Firefox

Center bootbox vertically

Выравниваем алерты, промпты и диалоги Bootbox.js по вертикали если указан класс v-center
bootbox.alert({message: "Прежде необходимо утвердить реестр по всем предприятиям!", className: 'v-center'});
bootbox.alert("Прежде необходимо утвердить реестр по всем предприятиям!");
$(function() {
	$(window).on('show.bs.modal resize', function(e){
		var setVpos = function() {
			$(this).find('.modal-dialog').css("margin-top", function() { return Math.max(0, ($(window).height() - $(this).height()) / 3) } );
		};
		if ($.isWindow(e.target))
			$('.modal.v-center:visible').each(setVpos);
		else if ($(e.target).hasClass('v-center')) 
			$(e.target).each(setVpos);
	})
});

General callback for multiple actions, jQuery

Ставим общий колбэк завершению нескольких асинхронных действий, воспользуемся «промисом» .promise().
1
2
3
4
jQuery( "#test" ).on( "click", "button", function() {
  var _this = jQuery(this);
  _this.prop( "disabled", true ).text( "Работаем" );
  _this.closest( "div" ).find( "div" ).each(function( i, o ) {
    jQuery( o ).slideToggle( 1000 * ( i + 1 ) );
  }).promise().done(function() {
      _this.prop( "disabled", false).text( "Жмем" );
  });
});