Полезные Javascript функции и приемы

Полезные Javascript функции и приемы

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

Автоматическое добавление аттрибута target=”_blank” ко всем внешним ссылкам

Часто при написании статей на сайте забывают поставить аттрибут target=”_blank” для внешних ссылок. С данным кодом можно об этом сильно не беспокоится:

var root = location.protocol + '//' + location.host;
$('a').not('[href^="/"]').not(':contains(root)').click(function(){
    this.target = "_blank";
});

Автоматическое исправление битых картинок

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

$(‘img’).error(function(){
    $(this).attr('src', 'img/broken.png');
});

Определение операций Копирования, Вырезания и Вставки

$("#textA").bind('copy', function(){
    $('span').text('copy behaviour detected!');
});
$("#textA").bind('paste', function(){
    $('span').text('paste behaviour detected!');
});
$("#textA").bind('cut', function(){
    $('span').text('cut behaviour detected!');
});

Определение Internet Explorer

Internet Explorer до сих пор остается головной болью верстальщиков и frontend-программистов. Для определения IE можно использовать:

$(document).ready(function(){
    if (navigator.userAgent.match(/msie/i)) {
        alert("I am an old fashioned Internet Explorer");
    }
});

Определение ширины экрана

Сейчас все большую популярность набирают мобильные браузеры. И, в связи с этим, появилась необходимость определять то или иное поведение элементов на странице в зависимости от размера экрана посетителя. Определить текущий размер можно:

var responsive_viewport = $(window).width();

/* if is bolow 481px */
if (responsive_viewport < 481) {
    alert('Viewport is smaller than 481px');
} /* end smallest screen */

Запрет на пробелы в текстовых полях и паролях

$('input.nospace').keydown(function(e){
    if (e.keyCode == 32) {
        return false;
    }
});

Эффект затемнения при наведении

Просто красивый эффект для картинок.

$(document).ready(function(){
    $('.thumbs img').fadeTo('slow', 0.6);

    $('.thumbs img').hover(function(){
        $(this).fadeTo('slow', 1.0);
    }, function(){
        $(this).fadeTo('slow', 0.6);
    });
});

Замена одного html тега другим

$('li').replaceWith(function(){
    return $("<div />").append($(this).contents());
});

Плавный скроллинг к началу страницы

$("a[href='#top']").click(function(){
    $("html, body").animate({scrollTop: 0}, "slow");
    return false;
});

Прикрипление элемента к верху экрана

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

$(function(){
    var $win = $(window);
    var $nav = $('.mytoolbar');
    var navTop = $('.mytoolbar').length && $('.mytoolbar').offset().top;
    var isFixed = 0;

    processScroll();
    $win.on('scroll', processScroll);

    function processScroll() {
        var i, scrollTop = $win.scrollTop();

        if (scrollTop >= navTop && isFixed) {
            isFixed = 1;
            $nav.addClass('subnav-fixed');
        } else if (scrollTop <= navTop && isFixed) {
            isFixed = 0;
            $nav.removeClass('subnav-fixed');
        }
    }
});

Проверка валидности емейла

function validateEmail(email) {
    var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
}

debounce

Возвращает функцию, которая выполняется спустя N миллисекунд после последнего вызова. Если передан параметр immediate, то выполнение будет происходить песле первого вызова, а не после последнего.

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

Пример использования:

var myEfficientFn = debounce(function() {
    // All the taxing stuff you do
}, 250);
window.addEventListener('resize', myEfficientFn);

debounce обеспечивает единичное выполнение функции в течении заданного промежутка времени. Это может использоваться при часто срабатывающих событиях.

Получение абсолютного URL

Получение абсолютного адреса из переменной не так просто, как кажется. Существует способ, который работает даже, если вы не предоставите все параметры URL (иногда это и невозможно):

var getAbsoluteUrl = (function() {
    var a;

    return function(url) {
        if(!a) a = document.createElement('a');
        a.href = url;

        return a.href;
    };
})();

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

getAbsoluteUrl('/post/javascript-snippets/');
// http://knigun.com/post/javascript-snippets/

insertRule

Как известно, мы может получить NoteList из селектора (через document.querySelectorAll) и применить для всех них стили, но более эффективно применить эти стили к селектору, как это делается в css:

var sheet = (function() {
    // Create the <style> tag
    var style = document.createElement('style');

    // Add a media (and/or media query) here if you'd like!
    // style.setAttribute('media', 'screen')
    // style.setAttribute('media', 'only screen and (max-width : 1024px)')

    // WebKit hack :(
    style.appendChild(document.createTextNode(''));

    // Add the <style> element to the page
    document.head.appendChild(style);

    return style.sheet;
})();

Применение:

sheet.insertRule("header { float: left; opacity: 0.8; }", 1);

Это особо удобно, когда работаете с динамическим контентом через AJAX. Если вы применяете стили к селектору, то вам не надо беспокоится о применении этих стилей к каждому элементу, который соответствует селектору.

isNative

Знание является ли функция нативной или нет, может помочь в решении переопределять ее или нет.

;(function() {

  // Used to resolve the internal `[[Class]]` of values
  var toString = Object.prototype.toString;

  // Used to resolve the decompiled source of functions
  var fnToString = Function.prototype.toString;

  // Used to detect host constructors (Safari > 4; really typed array specific)
  var reHostCtor = /^\[object .+?Constructor\]$/;

  // Compile a regexp using a common native method as a template.
  // We chose `Object#toString` because there's a good chance it is not being mucked with.
  var reNative = RegExp('^' +
    // Coerce `Object#toString` to a string
    String(toString)
    // Escape any special regexp characters
    .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
    // Replace mentions of `toString` with `.*?` to keep the template generic.
    // Replace thing like `for ...` to support environments like Rhino which add extra info
    // such as method arity.
    .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );

  function isNative(value) {
    var type = typeof value;
    return type == 'function'
      // Use `Function#toString` to bypass the value's own `toString` method
      // and avoid being faked out.
      ? reNative.test(fnToString.call(value))
      // Fallback to a host object check because some environments will represent
      // things like typed arrays as DOM methods which may not conform to the
      // normal native pattern.
      : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
  }

  // export however you want
  module.exports = isNative;
}());

once

Часто требуется обеспечить единичное выполнение функции.

function once(fn, context) {
    var result;

    return function() {
        if(fn) {
            result = fn.apply(context || this, arguments);
            fn = null;
        }

        return result;
    };
}

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

var canOnlyFireOnce = once(function() {
    console.log('Fired!');
});

canOnlyFireOnce(); // "Fired!"
canOnlyFireOnce(); // nop

Данная функция гарантирует, что данный код будет выполнен только один раз. Используется для защиты от повторной инициализации.

poll

Иногда вы не можете подключится к какому-то событию для проверки интересующего вас состояния. Если события нету, то проверять состояние нужно периодически через определенные интервалы:

function poll(fn, callback, errback, timeout, interval) {
    var endTime = Number(new Date()) + (timeout || 2000);
    interval = interval || 100;

    (function p() {
            // If the condition is met, we're done!
            if(fn()) {
                callback();
            }
            // If the condition isn't met but the timeout hasn't elapsed, go again
            else if (Number(new Date()) < endTime) {
                setTimeout(p, interval);
            }
            // Didn't match and too much time, reject!
            else {
                errback(new Error('timed out for ' + fn + ': ' + arguments));
            }
    })();
}

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

// Usage:  ensure element is visible
poll(
    function() {
        return document.getElementById('lightbox').offsetWidth > 0;
    },
    function() {
        // Done, success callback
    },
    function() {
        // Error, failure callback
    }
);
 
comments powered by Disqus