• Как пушить на github чтобы не вводить каждый раз логин и пароль?

    bukinion
    @bukinion
    Некороткий мануал по SSH + GitHub & BitBucket (на Win, почти тоже и на Lin)

    Вначале надо найти ключи
    $ ls -al ~/.ssh
    # Спискок файлов в директории .ssh, если они есть
    # id_rsa.pub # Нам интересны эти два брата, точнее этот публичный код (паб)
    # id_rsa # Это для сверки с пабом


    Если их нет, то будем генерить, после чего ласково попросят пароль, он должен быть сложным, в конечном итоге вводится он будет только один раз при старте сессии.
    $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    # Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]
    # Enter passphrase (empty for no passphrase):
    # Enter same passphrase again:


    Кстати, пароль можно и поменять:
    $ ssh-keygen -p # Введете старый, а потом новый.

    Консоль выведет следующее:
    # Your identification has been saved in /Users/you/.ssh/id_rsa.
    # Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
    # The key fingerprint is:
    # 01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:db your_email@example.com


    Теперь надо добавить ваши ключи в ssh-агент
    Удостоверьтесь в том, что он у вас есть — запустите
    $ ssh-agent -s

    Должен быть следующий однострочный (!) вывод, номер pid будет другим, все остальное от лукавого:
    Agent pid 59566

    Если нет, то скорее всего в терминале другая оболочка, тогда:
    $ eval $(ssh-agent -s)
    Agent pid 59566


    Вот теперь можно добавить ключи в ssh-агент
    $ ssh-add ~/.ssh/id_rsa

    Далее, добавим ключи в VCS-сервисы github и bitbucket, для этого скопируйте содержимое id_rsa.pub, и вставьте в настройках своего аккаунта на VCS (например, "SSH and GPG keys" для Github). Активируем ключи.

    для github:
    $ ssh -T git@github.com

    чуть длинней, для bitbucket, вначале надо создать файл-конфиг, ~/.ssh/config, куда добавить следующие строки:
    Host bitbucket.org
    IdentityFile ~/.ssh/id_rsa # Тут приватный ключ!


    После чего запустить следующую команду:
    $ ssh -T git@bitbucket.org

    В каждом случае, если все пройдет успешно, то вы получите следующие сообщения:
    Hi #{username}! You've successfully authenticated, but GitHub does not provide shell access.


    или
    conq: logged in as tutorials.
    You can use git or hg to connect to Bitbucket. Shell access is disabled.


    К слову, что Github, что Bitbucket выдали мне в этот раз такое:
    Thу authenticity of host 'github.com (192.30.253.113)' can't be established.
    RSA key fingerprint is 12:12:12...12.
    Are you sure want to conecting (yes/no)?


    Ответил yes, консоль что-то ответила и все работает.

    Если же вы используете алиасы для хостов, то и активация должна быть через алиас:

    $ ssh -T git@alias


    Если работаете с Sourcetree (рекомендую для винды), то есть такой момент, что программа не принимает стандартный формат этих ключей и что бы работать с программой через ssh придется из полученного ключа (приватный) сгенерировать их в другом формате понятном putty. Для этого используется программа puttygen. Которая входит в поставку Sourcetree.


    Занудно, но уже финал близок, далее нам нужно настроить ~/.bashrc, которого на винде нет, именно он будет содержать инициализационные настройки для консоли и запускать ssh-агент, который будет включать ваши ключи, запоминать сессию:
    # Note: ~/.ssh/environment should not be used, as it
    #       already has a different purpose in SSH.
    
    env=~/.ssh/agent.env
    
    # Note: Don't bother checking SSH_AGENT_PID. It's not used
    #       by SSH itself, and it might even be incorrect
    #       (for example, when using agent-forwarding over SSH).
    
    agent_is_running() {
        if [ "$SSH_AUTH_SOCK" ]; then
            # ssh-add returns:
            #   0 = agent running, has keys
            #   1 = agent running, no keys
            #   2 = agent not running
            ssh-add -l >/dev/null 2>&1 || [ $? -eq 1 ]
        else
            false
        fi
    }
    
    agent_has_keys() {
        ssh-add -l >/dev/null 2>&1
    }
    
    agent_load_env() {
        . "$env" >/dev/null
    }
    
    agent_start() {
        (umask 077; ssh-agent >"$env")
        . "$env" >/dev/null
    }
    
    if ! agent_is_running; then
        agent_load_env
    fi
    
    # if your keys are not stored in ~/.ssh/id_rsa or ~/.ssh/id_dsa, you'll need
    # to paste the proper path after ssh-add
    if ! agent_is_running; then
        agent_start
        ssh-add
    elif ! agent_has_keys; then
        ssh-add
    fi
    
    unset env


    И снова не финал, скорее всего так как вы не пользовались SSH, то ваши уже существующие локальные репо будут работать по http/https, поэтому надо сменить адреса. Адреса удаленных репозиториев проверяются командой $ git remote -v. Для смены адресов git есть специальная команда: $ set-url, ввести следующее:
    $ git remote set-url origin git@github.com:USERNAME/OTHERREPOSITORY.git


    Вернуть все на Родину можно аналогично
    Ответ написан
    1 комментарий
  • Git: объясните «на пальцах» разницу между rebase и cherry-pick?

    @Nkly777
    git chery-pick - ты забираешь комиты из одной ветки в другую, это бывает полезно когда изменения сделаные другим разработчиком в его ветке, прямо сейчас нужны тебе в твоей ветке, и что бы не писать этот код заново, ты забираешь его комит себе в ветку

    git rebase master - ты синхронизируешься с главной веткой в которую коммитят все разработчики проекта, это полезно когда кто-то изменил участок кода с которым ты сейчас работаешь в своей ветке, дабы через неделю ты смог без проблем смержиться с master веткой. Обычно делается каждое утро перед началом рабочего дня и в конце когда фича готова.

    git merge - обычно используется когда у вас 2 и более master ветки (к примеру master и prototype) в этих ветках очень много комитов (и rebase здесь не подходит) и обчно через пару недель, maintainer репозитория наработки из prototype ветки "сливает" в master ветку по средствам этого самого git merge

    P.S. Что бы легче предствить разницу между git merge и git rebase. Представь что merge как собачка на молнии у одежды - "сшивает" комиты по дате их создания.
    В то время как git rebase как пожарная лестница - при применении твои коммиты крепится на конец родительской ветки

    git merge используйте для мержа фич и фиксов в master ветку (как и делает это Github)
    а git rebase используется для своей ветку в которой вы работаете над фичей что бы забрать последние изменения с master ветку (для этого есть очень удобная команда `git pull --rebase origin master`, аналог 3х команд (`git checkout master; git pull origin master; git checkout mybrach; git rebase master`)
    Ответ написан
    2 комментария
  • Как реализовать авторизацию пользователя на стеке React Redux Node?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Пригодится jwt. (гугл)

    В общих словах: вам нужно выдать юзеру токен. С этим токеном юзер будет выполнять запросы к вашим защищенным методам api (вы можете оставить какие-то методы "без токена").

    Node.js часть
    Пример роута на логин (сделано не лучшим образом, в плане коллбэков, но что нашлось под рукой...):

    auth.js
    ...
    const v4 = require('node-uuid').v4
    const jwt = require('jsonwebtoken')
    ...
    router.post('/signin', (req, res, next) => {
    
      // валидация, например... 
    
      if (errors) {
        return res.status(400).json({ errors })
      } else {
        // поиск юзера в базе, сравнение хэша и прочие необходимые операции
        ...
       // допустим все ок, нужно ответить токеном
      // генерируем необходимые опции и сам токен
    
            const payload = {
              _id: user._id,
              iss: 'http://localhost:3000',
              permissions: 'poll',
            }
            const options = {
              expiresIn: '7d',
              jwtid: v4(),
            }
            const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
            jwt.sign(payload, secret, options, (err, token) => {
              // отвечаем токеном, для будущих запросов с клиента
              return res.json({ data: token })
            })
         ...
    })
    
    module.exports = router;


    Пример защищенного роута (метода, который требует токен):
    ...
    const jwt = require('jsonwebtoken')
    const Poll = require('../models/poll')
    ...
    
    const requireToken = (req,res,next) => {
      const token = req.headers['x-api-key']
      const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
    
      jwt.verify(token, secret, (err, decoded) => {
        if (err) {
          return res.status(401).json({ error: err.message })
        }
        req.params.userId = decoded._id
        next()
      })
    }
    ...
    
    // обратите внимание на requireToken - функция вызывается при каждом обращении к роуту
    // то есть при каждом PUT запросе по адресу (например: PUT api/v1/products/1238914)
    // будет вызываться requireToken
    
    router.put('/:id', requireToken, (req, res, next) => {
      const { productId } = req.body
      const userId = req.params.userId
    
      Poll.findById(req.params.id)
        .populate({ path: 'products' })
        .exec((err, poll) => {
            // ... необходимые действия в базе, в процессе успешного зачтения голоса...
        }
    })


    Клиентское приложение:

    Типичный ActionCreator (в качестве библиотеки для запросов можно взять bluebird, isomorphic-fetch, да хоть нативный xhr)
    actions/LoginActions.js

    export function login(data) {
      return dispatch => {
        dispatch({ type: LOGIN_REQUEST })
    
        // request в данном случае - https://github.com/KyleAMathews/superagent-bluebird-promise
        return request.post(`${API_ROOT_V1}/auth/signin`)
          .send(data)
          .then(res => {
            if (!res.ok) {
              dispatch({ type: LOGIN_FAILURE })
            } else {
              dispatch({
                type: LOGIN_SUCCESS,
                data: res.body.data,
              })
              //сохранение токена в localStorage
              localStorage.setItem('cks_token', res.body.data)
            }
          }, err => {
            dispatch({ type: LOGIN_FAILURE })
          })
      }
    }


    Пример голосования с токеном (выше, в node.js части был метод апи, а это PUT запрос с клиента)

    export function vote(productId, voteId) {
      return dispatch => {
        dispatch({ type: POLL_VOTE_REQUEST })
    
        return request.put(`${API_ROOT_V1}/api/v1/vote/${voteId}`)
          .set('X-API-Key', localStorage.getItem('cks_token')) // установка ТОКЕНА в заголовок 'X-API-Key'
          .send({ productId })
          .then(res => {
            if (!res.ok) {
              dispatch({ type: POLL_VOTE_FAILURE })
            } else {
              dispatch({
                type: POLL_VOTE_SUCCESS,
                data: normalize(res.body.data, schema.poll),
              })
            }
          }, err => {
            dispatch({ type: POLL_VOTE_FAILURE })
          })
      }
    }


    Надеюсь код формы с кнопкой "голосовать" не трубется.
    ====

    Все это можно организовать удобнее, например, выставлять токен всем запросам автоматически (речь про клиентскую часть):
    import fetch from 'isomorphic-fetch'
    ...
    const defaultHeaders = {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    }
    
    function buildHeaders() {
      const authToken = localStorage.getItem('TOKEN')
      return { ...defaultHeaders, Authorization: authToken }
    }
    ...
    export function httpPost(url, data) {
      const body = JSON.stringify(data)
    
      return fetch(url, {
        method: 'post',
        headers: buildHeaders(),
        body: body,
      })
      .then(... код оработки запроса ...)
    }


    ===

    Проверить наличие токена, можно с в роутере, с помощью хука на onEnter.

    root.js
    ...
    <Provider store={store}>
          <Router history={routerHistory}>
            {configRoutes(store)} // Роуты создаются функцией, чтобы можно было использовать внутри нее store.getState()
          </Router>
        </Provider>
    ...


    routes.js
    export default function configRoutes(store) {
      function _ensureAuthenticated(nextState, replace, callback) {
        const { dispatch } = store
        const { session } = store.getState()
        const { currentUser } = session
        let nextUrl
    
        if (!currentUser && localStorage.getItem('cks.token')) {
          dispatch(getCurrentAccount())
        } else if (!localStorage.getItem('cks.token')) {
          replace('/signin')
        }
        callback()
      }
    
      return (
        <Route path='/' component={App}>
          <Route path='/signin' component={SigninContainer} />
          <Route path='/signup' component={SignupContainer} />
    
          <Route path='/locked' component={AuthenticatedContainer} onEnter={_ensureAuthenticated}>
            <Route component={LockedArea}>
              <Route path='/locked/a' component={A} />
              <Route path='/locked/b/:id' component={B} />
              <Route path='/locked/c' component={C} />
            </Route>
          </Route>
        </Route>
      )


    Остается только создать AuthenticatedContainer в котором проверять: есть ли currentUser (в рамках этого примера) и если нет - возвращать false. А если есть - this.props.children (в которых будут дальнейшие роуты..)
    ===

    Итого:
    1) у вас есть API написанное на node.js.
    2) У этого API есть защищенные методы, которые проверяют наличия токена в http-запросе. Токен выдается при запросе на логин. Само собой, операция логина (то есть POST запрос на your-api/login) не требует токена.
    3) После удачного логина, вы получаете в ответе на свой запрос токен (это уже внутри клиентского кода, и если мы говорим о redux - то внутри асинхронного вызова в actions)
    4) Сохраняете токен (например, в localStorage)
    5) Во все необходимые http-запросы устанавливаете заголовок с токеном
    Ответ написан
    15 комментариев
  • Стоит ли переходить на React.PureComponent по-умолчанию?

    PQR
    @PQR
    React.PureComponent реализует метод shouldComponentUpdate таким образом, что он делает поверхностное сравнение props и state (не глубокое). Вот собственно код:
    https://github.com/facebook/react/blob/c8fbdac2271...
    shouldUpdate =
                !shallowEqual(prevProps, nextProps) ||
                !shallowEqual(inst.state, nextState);


    Что такое shallowEqual? Это по сути сравнение оператором === каждого элемента из prevProps с каждым элементом из nextProps. На всякий случай дам ссылку на реализацию для полного понимания: https://github.com/facebook/react/blob/6963ea4bfcd...

    В итоге всё зависит от структуры ваших props. Если в props вы передаёте объекты которые иногда мутируются, т.е. по ссылке они равны ===, но внутри какие-то данные поменялись (что само по себе выглядит странно в экосистеме redux + reselect, но вполне возможно технически), тогда использование PureComponent вам всё поломает, т.к. на экране какие-то компоненты перестанут перересовываться!

    Если же у вас всё по уму, данные которые передаются через props являются скалярными типами (string, int, float, bool) или immutable объектами, тогда смело используйте PureComponent - в некоторых случаях он поможет избавиться от лишних вызовов render.

    Важное замечание: PureComponent нужно использовать только для так называемых presentational components, т.е. для тех компонент, которые НЕ обёрнуты в вызов redux connect().

    Для container components (т.е. тех компонент, которые обёрнуты в redux connect()) нет смысла наследоваться от PureComponent, т.к. метод connect() оборачивает ваш компонент своей реализацией shouldComponentUpdate, которая также использует shallowEqual. Если вы по недосмотру унаследуете container component от PureComponent - ошибок не будет, но это не имеет никакого смыла, т.к. ваш код по сути будет дважды делать shallowEqual, а зачем делать лишнюю работу?

    Подводя итог, рецепт такой:
    - presentational components наследуем от React.PureComponent
    - container components (которые обёрнуты в redux connect()) наследуем от старого доброго React.Component
    Ответ написан
    1 комментарий
  • Как правильно писать модульные Javascript библиотеки?

    OlegTar
    @OlegTar
    программист .NET, Javascript, Perl
    Например, так

    toddmotto.com/mastering-the-module-pattern

    также есть библиотека require.js, позволяющая разбивать код на модули.
    Здесь есть примеры и сама библотиека: requirejs.org

    require.js можно использовать в node.js
    Ответ написан
    Комментировать
  • Где искать интересные проекты на github для начинающего react разработчика?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Могу посоветовать конкретизировать поиск. Например:
    react dashboard
    react weather app
    react reddit client
    react youtube client
    react tic tac toe
    etc
    Ответ написан
    Комментировать
  • Какова суть генерации своих событий в JavaScript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Попробую на пальцах объяснить.

    Событие – это конверт, на котором написано его название. Внутрь конверта можете вложить что-нибудь, а можете оставить конверт пустым.

    Элемент – это столик. Кто угодно может подойти и положить на столик свой конверт.

    Слушатель – это мужик, который топчется около столика и смотрит, нет ли чего с интересующим его названием. Может несколько человек поджидать конвертики с определённым названием – прочтут все, если только в конверте не написано «по прочтении съесть» – тогда кто-то съест и дальше не передаст.

    Как создать/отправить конверт. В любом месте кода создайте конверт и дайте ему название: var myEvent = new Event('teaTime'); Остается положить конверт на нужный столик:
    document.getElementById('stolik').dispatchEvent(myEvent);


    Чтобы в событие вложить какие-то данные, нужно использовать другой конструктор и передать нагрузку в поле detail:
    var event = new CustomEvent('saySomething', { detail: "Hello there!" });


    Для чего нужно создавать свои события? Чтобы развязать куски кода. Например, в разных местах документа можно нажать на кнопку повторяющегося виджета. Виджет создаст на document событие "widgetClicked". А ещё несколько одинаковых компонентов в странице, слушающих document на предмет события "widgetClicked", получат пинок и что-нибудь вытворят.
    Ответ написан
    2 комментария
  • Где используются прототипы, наследование в JS приложениях?

    yurakostin
    @yurakostin
    Front-end developer
    Здравствуйте.
    На самом деле всё проще.
    Не обижайтесь, но вы просто не так хорошо знаете сам javascript.

    1. prototype - ссылка на прототип объекта.
    Array.prototype, Number.prototype. В нём хранятся методы и свойства этого объекта, а также... (далее переходим к __proto__)

    2. __proto__ - тоже ссылка на прототип. Например, введите в консоли [] и раскройте ветвь. У вас всего два свойства. Одно - length - количество элементов в массиве. Другое - __proto__. А где же все методы, которые мы можем использовать с массивами filter, map, slice и так далее? Они лежат в __proto__. Более подробно здесь.

    3. inheritance соответственно - наследование. JS построен на прототипной парадигме (надеюсь, я тут не наврал). Array наследуется от Object. Это можно легко увидеть, посмотрев Array.prototype. Там вы увидите тот самый __proto__, являющийся ссылкой на Object.prototype. Вся инфа по ссылке выше.

    4, 5. call и apply постепенно уходят из обихода, но тем не менее про них важно знать и уметь ими пользоваться. Эти методы позволяют вызвать функцию в контексте, который вам необходим.

    Например вам нужно вызвать метод какого-то объекта, который работает с this в контексте другого объекта, у которого этого метода нет. Вы можете сделать следующее:
    var o_1 = {
    	name: 'Peter',
    	hello: function () {
    		console.log('Hello, ' + this.name);
    	}
    };
    
    var o_2 = {
    	name: 'Jane'
    };
    
    o_1.hello.call(o_2); // Фактически вы говорите "вызови метод такой-то для объекта такого-то"


    Для передачи аргументов в "заимствованную" функцию оба метода принимают аргументы, каждый по-своему.
    var o_1 = {
    	name: 'Peter',
    	hello: function () {
    		console.log('Hello, ' + this.name);
    	},
            sum: function (a, b) {
    		console.log(`${this.name} sum a and b to ${a + b}`);
    	}
    };
    
    var o_2 = {
    	name: 'Jane'
    };
    
    o_1.sum.call(o_2, 2, 4);
    o_1.sum.apply(o_2, [1, 2]);


    Отличие между этими двумя методами в том, как они принимают аргументы, которые попадут в функцию.
    call принимает список аргументов, начиная со второго, а apply, соответственно, принимает массив.

    Также, ничто не мешает вам вызвать функцию, которая не нуждается в контексте, для этого первым аргументом можно передать null.

    var o = {
    	sum: function (a, b) {
    		console.log(a + b);
    	}
    }
    o.sum.call(null, 1, 2);
    o.sum.apply(null, [1, 2]);


    Подробнее тут.

    6. bind тоже довольно простая штука. Отчасти он похож на предыдущие два метода, за исключением того, что он не вызывает функцию сразу же.
    Основная его задача - вернуть функцию, которая будет вызвана для нужного вам контекста.

    var o = {
    	a: 1,
    	b: 2,
    	sum: function () {
    		console.log(this.a + this.b);
    	}
    };
    
    var o2 = {
    	a: 10,
    	b: 20
    };
    
    var o2Sum = o.sum.bind(o2);
    
    o2Sum();


    Также с помощью bind можно каррировать функции.
    Всё есть здесь

    PS: надеюсь, код не содержит ошибок и я нигде не налажал и всё правильно рассказал.
    Ответ написан
    4 комментария
  • Верстка в Linux?

    zorro76
    @zorro76
    Я перешел с винды на Ubuntu 3 месяца назад. Все ок и все работает должным образом. Начиная от командной строки и заканчивая редактором. А то что нет полноценного Photoshop это миф. Посмотри тут https://www.youtube.com/watch?v=wjmQJckOATM И собственно зачем Photoshop верстальщику, понятно что для посмотреть макет и нарезать, все. Правда все это можно сделать и на gimp, но тут дело вкуса. Лично я за продукт Adobe assets.adobe Все остальное настраивается и работает на Linux в разы проще и быстрее. node, npm, bower, gulp, grunt, git ... да собственно все, что нужно фронт-энд разработчику. Тот же looftblog выложил видео с настройкой среды разработчика на Linux https://www.youtube.com/watch?v=DfSm7SVq4LA

    UPD: и да сейчас вообще Avocode рулит
    Ответ написан
    4 комментария
  • Возможно ли сделать квадратный блок авто ширины средствами HTML+CSS?

    SowingSadness
    @SowingSadness
    web-разработчик
    Оторвал бы руки, за то что ты пишешь вопрос курсивом
    <div class="wrapper">
      <div class="box"></div>
    </div>

    .wrapper {
      width: 100px;
      margin: 0 auto;
    }
    
    .box {
      background: goldenrod;
      margin-left: auto;
      margin-right: auto;
      padding-top: 50%;
      padding-bottom: 50%;
    }
    Ответ написан
    8 комментариев
  • Как реализовать не стандартные (обрезанные) границы в блоке,за которым имеется цветной фон?

    Petroveg
    @Petroveg
    Миром правят маленькие с#@&ки
    jsfiddle.net/petroveg/dL91e497
    Обращаем внимание на связанные величины.

    Вот вам ещё немного магии codepen.io/cleric/pen/oDsbh
    Скруглённые края. 20px — связанная величина.
    Ответ написан
    1 комментарий
  • Нужно ли официальное трудоустройство фрилансера?

    sulla
    @sulla
    @SV0L0Ch - есть малый совет почитайте Трудовой кодекс :)

    В текущей ситуации в стране есть несколько вариантов решения "придуманной вами проблемы"

    1. открыть ИП и морочиться с доходами / расходами и отчётность
    2. положить трудовую книжку в организацию на 1/4 - 1/10 ставки и помелочи им что-то делать (Вы же правильный человек :)

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

    из плюсов:
    - у Вас реально будет договор в котором прописана ответственность сторон
    - Вам будет благодарна "блузгалтерия" любой фирмы работающей в белую, ибо не нао придумывать варианты вывода
    - Кидать с черевато для заказчика
    - заказчик платит за вас все налоги (кстати если будет ИП заказчик может за вас же и платить 6%, вместо 13%, вот тут надо уточнять нужна ли отчётность с Вас, по идее нужна в любом случае)

    из минусов:
    - время на согласование у Юристов организации (если они есть)
    - заказчика надо убедить что договор нужен ему и его надо подписать
    Ответ написан
    2 комментария
  • Одностраничный сайт, как сделать такой эффект?

    @ikeagold
    htmlbook.ru/samhtml/yakorya
    Только там же еще параллакс.
    Пример якоря:
    <a href="#onas">О нас</a>
    <div name="onas"></div>

    Для плавного скролла:
    jsfiddle.net/YtJcL
    Ответ написан
    2 комментария
  • Договор с фрилансером - как не платить налоги?

    opium
    @opium
    Просто люблю качественно работать
    По сути оплата налогов личное дело фрилансера и он сам должен их оплачивать.
    Так что просто платите ему, а уж он там платит или не платит это его проблемы.
    Ответ написан
    3 комментария
  • Что означает конструкция (function($){$(function(){ })})($)?

    GeneMoss
    @GeneMoss
    void
    $(function(){}) — это мы запускаем действие в момент загрузки страницы. А оборачиваем в анонимную функцию (function($){ })($);, чтобы избежать конфликта имен с $.

    Автор плагина предусмотрел случай, когда доллар занят под другую библиотеку/функцию/переменную. Чтобы избежать конфликта имен, достаточно будет заменить доллар на jQuery, вот так (хотя сразу так и нужно было писать):
    (function($){$(function(){
        $('select').styleThis();
    })})(jQuery);


    Т.е. передав один раз нужный параметр, нам нет нужды переписывать весь плагин.
    Ответ написан
    1 комментарий