Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

JQuery поиск обработчика события объекта

#jquery #dom #события


Мне нужно найти, какие обработчики событий записаны на объекте.

Например:

$("#el").click(function() {...});
$("#el").mouseover(function() {...});


На $("#el") записаны события click и mouseover.

Есть ли функция, чтобы узнать это, и можно ли выполнить итерацию по обработчикам событий?

Если это невозможно в объекте jQuery с помощью правильных методов, возможно ли это
для обычного объекта DOM? 

Переведено с: https://stackoverflow.com/questions/2518421/
    


Ответы

Ответ 1



Начиная с jQuery 1.8, информация о событиях больше не доступна из «public API» для данных. Прочтите это сообщение в блоге jQuery. Теперь, для того чтобы узнать список событий записанных на объекте, нужно использовать это: jQuery._data( elem, "events" ); elem должен быть элементом HTML, а не объектом jQuery или селектором. Обратите внимание, что это внутренняя, «частная» структура, и ее не следует изменять. Используйте это только для целей отладки. В старых версиях jQuery вам может потребоваться использовать старый метод: jQuery( elem ).data( "events" ); Пример: $('#el').click(function() { $(this).text('Нажали!'); }) $('#el').mouseover(function() { $(this).text('Поводили мышкой!'); }); // Получаем события var elem = $('#el').get(0); console.log( $._data(elem, "events") );
Текст


Отличия в оптимизации C и C++

#cpp #c


Какой код компилируется Си и С++, корректно работает, но при этом может отличается
по быстродействию вследствие различий стандартов C и C++?

Пример: malloc(sizeof('x') * 100500) выделит в sizeof(int) раз больше памяти в Си,
что теоретически может замедлить программу.
    


Ответы

Ответ 1



Если абстрагироваться от вопросов качества реализации компиляторов С vs. С++, то отличаться по быстродействию "один и тот же код" в С и С++ может только в том случае, если он отличается по семантике. То есть "одним и тем же кодом" в такой ситуации он будет только с чисто косметически-визуальной точки зрения. Можно грубо выехать на различиях в правилах name lookup struct S { int a[10]; }; int main() { struct Local { struct S { int a[10000]; } s; }; struct S s = { 0 }; // `sizeof s`??? } В языке С здесь объявляется и обнуляется "большой" объект, а в С++ - "маленький". Но это уж слишком грубо. Свойство языка С++ бережно сохранять lvalue-ность результатов выражений приведет к тому, что цикл for (unsigned n = sizeof (1 ? "Hello" : "World"); n > 0; --n) ; будет выполняться разное количество раз в С и в С++. Это тоже довольно грубый прием. Далее стоит упомянуть следующее const int N = 10; int A[N][N][N]; В языке С++ это - обычный массив, а в языке С - это Variable Length Array с потенциальными накладными расходами во время выполнения. Продолжая тему VLA, операнд вот такого sizeof в языке С является вычислимым выражением (подразумевая вышеприведенное объявление A) unsigned n = sizeof A[rand() % N][rand() % N]; И хотя, согласно спецификации языка С, вычисления выражений-индексов в данном случае не требуется (ибо результат от них не зависит), компилятор имеет право их вычислить (GCC, что интересно, вычисляет). В C++ же операнд sizeof вычислимым не является никогда, т.е. такой sizeof вычисляется во время компиляции и выполнимого кода не порождает. Ворох мелочей может скрываться в различиях правил sequencing этих языков. То же свойство сохранения lvalue-ности результатов выражений в С++ приводит к тому, что его правила sequencing более строги и ограничивающи, чем аналогичные правила в С. Это теоретически может привести к более эффективному коду в С. (Но придумать пример, где бы это давало осязаемый эффект навскидку непросто.) Потенциальная необходимость обработки исключений в С++ и раскрутки стека - еще одна причина, по которой практически любой идентичный С и С++ код может быть странслирован менее эффективно в С++.

Ответ 2



Теоретически fabs((char)x) и собратья из cmath, имеющие перегрузки для целочисленных типов, могут работать быстрее. Появились в С++11, если не ошибаюсь.

Содержит ли строка заданную подстроку?

#javascript


Каким способом можно определить что в строке есть искомый текст?

Перевод вопроса "How to check whether a string contains a substring in JavaScript?"
    


Ответы

Ответ 1



Способов, на самом деле, достаточно много: String#indexOf(str: String[, fromIndex: Number]): Number - один из старейших способов. Возвращает найденную позицию str или, если подстрока не найдена, -1. Параметр fromIndex определяет отступ поиска. Важно: В условии необходимо использовать сравнение и обязательно строгое: Без сравнения, -1 (отсутствие подстроки) трактуется как true. Может возвращать 0 (совпал первый символ), что приводится обычным сравнением к false. 'Hello, world!'.indexOf('world'); // 7 'Hello, world!'.indexOf('o'); // 4, в конце hello 'Hello, world!'.indexOf('o', 5); // 8, вторая буква в world !!'Hello, world!'.indexOf('z'); // true, отрицательное число приводится к true !!'Hello, world!'.indexOf('H'); // false, 0 трактуется как false String#search([regexp: RegExp]): Number - тот же String#indexOf, только с регулярным выражением и отсутствием смещения. "Date of birth of Einstein: 3/14/1879".search(/\d{4}/); // 32 String#includes(searchString: String[, position: Number]): Boolean - более кошерный вариант String#indexOf с двумя отличиями: Возвращает Boolean, вместо позиции, что может быть более ожидаемым. Работает быстрее. Однако разница ощутима только на весьма больших объёмах, проверить. 'Hello, world!'.includes('o'); // true, в конце hello 'Hello, world!'.includes('o', 9); // false, после девятого символа нет 'o' String#match(regexp: RegExp): Array | Null - String#search на стероидах (однако, медленнее). Возвращает немного модифицированный массив с найденной подстрокой, позицией совпадения (index) и свойством input - строкой, в котором проходил поиск или Null, если регулярка ничего не нашла. Опционально, в массиве могут быть захваченные группы. При использовании флага g, вернутся все найденный совпадения (правда без групп и особых свойств): "Date of birth of Einstein: 3/14/1879".match(/(\d{4})/); // [0: "1879", 1: "1879", index: 32, input: "Date of birth of Einstein: 3/14/1879", length: 2] `Date of birth of Einstein: 3/14/1879; Date of birth of Hendrik Lorentz: 7/18/1853`.match(/(\d)\/(\d{2})\/(\d{4})/g); // [0: "3/14/1879", 1: "7/18/1853", length: 2] Есть ещё методы RegExp#test или RegExp#exec, который так же могут быть использованы для проверки, но это уже совсем другая история.

Почему я могу выполнить div для числа с точкой и Варианта в Делфи?

#delphi


С удивлением обнаружил, что числа с точкой могут быть целочисленно поделены на Variant
в Delphi. Простой пример:

var
  v: Variant;
begin
  v := 2.3;
  Tag := 5.1 div v; // 2
  Tag := 5.1 mod v; // 1
  Tag := 5.1 div 2; // [dcc32 Error] E2015 Operator not applicable to this operand type
  Tag := 5.1 mod 2; // [dcc32 Error] E2015 Operator not applicable to this operand type
end;


Похоже, что Delphi округляет левую и правую часть выражения перед выполнением div/mod
операторов.

Я полагал, что вышенаписанный код вызовет ошибку при компилировании всех 4 строк,
т.к. в моем понимании, операторы div/mod не применимы к числам с точкой от слова "совсем".
Похоже что это не так.

Почему Delphi дает мне целочисленно поделить число с точкой на Variant, для чего
нужна эта возможность?
    


Ответы

Ответ 1



В справке по типу Variant есть следующее If an expression combines variants with statically-typed values, the statically-typed values are automatically converted to variants. Если в выражении используются переменные вариантных типов и статически-типизированные значения, статически-типизированные значения автоматически приводятся к вариантному типу. В справке по операторам Except for ^, is, and in, all operators can take operands of type Variant; Все операторы, кроме ^, is и in могут принимать операнды с типом Variant. Из этого следует, что в выражениях Tag := 5.1 div v; // 2 Tag := 5.1 mod v; // 1 число 5.1 было приведено к типу Variant При использовании типа Variant в операциях, если исходное значение не подходит для операции оно конвертируется в подходящее по определенным правилам. Правила указаны в специальной таблице.

Единый код (для расчета цены) на JS и PHP

#php #javascript


На чем можно записать алгоритм, который должен отрабатывать единым образом в JS и
в PHP (чтобы избежать дублирования кода)?

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

На сервере (php) расчет стоимости по заданным параметрам происходит заново, для оформления
заказа и записи в БД.

Получается дублирование кода - один и тот же алгоритм реализован и на JS, и на PHP.
При изменении приходится вносить правки и туда, и туда. Это проблема.

Получать стоимость  с сервера через AJAX во время изменения параметров пользователем
нельзя, так как это происходит несколько раз в секунду (посетитель перетаскивает ползунок
и в зависимости от его положения изменяется стоимость).

Вопрос в том, как записать этот алгоритм расчета в коде, едином и для JS и для PHP.
Я уже думал использовать v8js, но на хостингах такое пока не поддерживается.

Что еще можно попробовать для описания алгоритма, чтобы это можно было выполнять
и в PHP, и в JS без изменений?
    


Ответы

Ответ 1



Решение "в обход" — выкидывание реализации на JS "Каноническая" реализация на сервере однозначно должна быть, так что выкинуть можно только если реализацию на JS, вместо неё получать результат с сервера. Решение "в лоб" — язык над обоими Мне известен ровно один язык, способный собираться и в JS, и в PHP — Haxe. Но это добавление в проект ещё одного языка. Стоит ли оно того? Решение "боком" — преобразовать одну в другую Если алгоритм использует совсем мало фич языка, преобразовать одно в другое может быть возможно даже регулярными выражениями. Тут народ Паскаль в Си переводит препроцессором, может и у вас получится. Но этот костыль, скорее всего, будет одноразовым и после сколько-нибудь существенных правок потребует доработки. Повезёт ещё, если сообщит о проблемах преобразования (хотя бы падением результата), а не просто по-тихому поведёт себя иначе.

Ответ 2



Ну если захотеть извратиться, то можно замутить что-нибудь такое: var calculate = (function () { var $q, $res; return function calculate //0;/* })(); //*/ Впрочем, предварительно надо убедиться в поддержке браузерами комментария -->, который официально появляется только в ES6. JS: https://jsfiddle.net/us9m5n3g/1/ PHP: http://ideone.com/ByU8Cs PS: А вообще, Node.js :)

Как правильно оформить модели SQLAlchemy?

#python #архитектура #sqlalchemy #model


Попробую сформулировать вопрос.

Сейчас я изучаю Python и SQLAlchemy делая проект для себя. Создал таблицу User:

Model = declarative_base()

class User(Model):
    __tablename__ = "users"

    id = Column(Integer, primary_key = True)
    nickname = Column(String)
    email    = Column(String)
    password = Column(String)


Добавил туда несколько записей.

Допустим теперь я хочу проверить - существует ли какой либо пользователь с указанным
email? Я делаю следующее:

bool(session.query(exists().where(User.email == email)).scalar())


Как по мне - этот код абсолютно не читаем. Поэтому я вынес его (и другие подобные
функции работы с базой) в отдельный класс Users. И вызываю их по мере необходимости
в логике приложения.

class Users:
    def exists(email):
        return bool(session.query(exists().where(User.email == email)).scalar())

    def add(nick, email, password):
        pass # Тут код

    def email_exists(email):
        pass # Тут код

    def update(id, nick, email, password):
        pass # Тут код


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


Ответы

Ответ 1



Я когда-то делал подобным образом. Как по мне - нормальная реализация методов моделей. Неплохим решением будет создать базовый класс, от которого можно наследовать другие модели, а в самих методах добавлять нужную логику. Для своих нужд, работая с фреймворком Flask, написал такую такую штуковину: from ._base import db from sqlalchemy.exc import IntegrityError, InterfaceError from flask import flash from sqlalchemy import event from sqlalchemy.event import listen from sqlalchemy.orm.interfaces import MapperExtension from ..utils.redis import redis_store from sqlalchemy import inspect from sqlalchemy.ext.declarative import as_declarative, declared_attr from pickle import dumps, loads @as_declarative() class BaseExtension(MapperExtension): def after_insert(self, mapper, connection, instance): row = instance.query.filter_by(id = instance.id).first() payload = {'model': instance.__class__.__name__, 'data': instance.id, 'type': 'INSERT', 'row': row} redis_store.publish('realtime', dumps(payload)) def after_update(self, mapper, connection, instance): row = instance.query.filter_by(id = instance.id).first() payload = {'model': instance.__class__.__name__, 'data': instance.id, 'type': 'UPDATE', 'row': row} redis_store.publish('realtime', dumps(payload)) def after_delete(self, mapper, connection, instance): row = instance.query.filter_by(id = instance.id).first() payload = {'model': instance.__class__.__name__, 'data': instance.id, 'type': 'DELETE', 'row': row} redis_store.publish('realtime', dumps(payload)) class Base(db.Model): __abstract__ = True __mapper_args__ = { 'extension': BaseExtension() } id = db.Column(db.Integer, primary_key=True) created_at = db.Column(db.DateTime, default=db.func.current_timestamp()) modified_at = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp()) @classmethod def create(cls,**kwargs): c = cls(**kwargs) db.session.add(c) try: db.session.commit() flash((c.__tablename__).capitalize() + u' created successfully!', 'success') except IntegrityError: db.session.rollback() flash((c.__tablename__).capitalize() + u' created failed!' + u' IntegrityError', 'error') except InterfaceError: db.session.rollback() flash((c.__tablename__).capitalize() + u' created failed!' + u' InterfaceError', 'error') return c def __repr__(self): mapper = inspect(self).mapper ent = [] object_data = {col.key: getattr(self, col.key) if not col.key == 'created_at' and not col.key == 'password' and not col.key == 'modified_at' else None for col in mapper.column_attrs} return "{0}".format(object_data) Сейчас я вижу, сколько тут всего ненужного и неправильного, но во всяком случае, для саморазвития, это был хороший опыт. Во-первых, те поля, которые повторяются во всех моделях (id, created_at, modified_al) описываются единожды. Во-вторых, наследуемый create(), с обработкой некоторых исключений. В-третьих, события ORM (мой метод реализации которых считается устаревшим) after_insert, after_update, after_delete обрабатываются, и данные отдаются в redis. Я это делал для "real-time" передачи данных (нотификации, обновления данных в дашборде и пр.) В-четвёртых, __repr__, который так же универсален для всех моделей. Так же, сюда можно добавить так называемый 'soft-delete', который позволит не удалять данные из БД насовсем, а так же методы, чтобы доставать из базы "не удалённые", все и только удалённые. Кучу всего можно придумать при необходимости. В конечном счёте, один раз реализованный базовый класс сэкономит много времени и места в моделях.

Ответ 2



Вообще подход то правильный в духе ОО, но как правило session - не стоит использовать в модели, тем более как у вас в примере глобальную переменную session, лучше тогда ее передавать в метод/свойство. И в вашем примере есть некоторая неправильность на мой взгляд - методы указанные в примере должны быть classmethod - методами класса, ведь они не привязаны к экземпляру сущности Я бы посоветовал вам по возможности вместо обычных свойств/методов делать гибридные - на всякий случай. Вдруг потом понадобится делать запросы используя кусок логики свойства в конечных запросах они порой повышают читаемость.

Шаблонная функция

#cpp #шаблоны_с++


Есть шаблонная функция: 

template 
void function(T1 a, T1 b, T2 c) { ... }


Требуется, чтобы 3 параметр имел дефолтное значение. То есть хочется, чтобы было
как-то так:

template 
void function(T1 a, T1 b, T2 c = С) { ... }


Но при вызове функции от 2 аргументов выдает ошибку. Как я понимаю дело в втором
параметре шаблона. Нужно как-то тоже ему придать дефолтное значение.
    


Ответы

Ответ 1



Как бы это выразиться... Вы вызываете f(a,b) - и что должен делать компилятор, не имея никакой информации о типе третьего параметра? Тип тоже надо умолчать... Что-то вроде: template void f(T a, T b, U c = U(0)) { cout << a << " " << b << endl; cout << typeid(c).name() << endl; cout << c << endl; } int main() { f(0,1,3); f(0,1,3.0); f(0,1); }

Ответ 2



Аргументы по умолчанию не участвуют в процессе дедукции шаблонных параметров. Поэтому дедукция типа T2 из вызова функции function с двумя аргументами сделана быть не может быть сделана на основе типа C. Пользуйтесь перегрузкой вместо умолчательных аргументов template void function(T1 a, T1 b, T2 c) { ... } template void function(T1 a, T1 b) { function(a, b, C); }