Страницы

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

четверг, 23 мая 2019 г.

Тормозит css-анимация

Суть вопроса в следующем. На сайте есть sidebar (выезжающее справа меню), анимация которого построена на css-transitions. В неактивном состоянии sidebar имеет следующий код:
position: fixed; top: 0; bottom: 0; right: 0; opacity: 0; width: 300px; background: #fff; z-index: 9999; -o-transition: all 250ms ease-in-out; transition: all 250ms ease-in-out; transform: translate(300px, 0px);
в активном состоянии к нему добавляется класс с таким кодом:
transform: translate(0px, 0px); opacity: 1;
Проблема в том, что периодически наблюдаются тормоза при открытии/закрытии меню. Профайлер Google Chrome толком не дает никакой информации по причине подвисаний. На кадр анимации уходит всего 1-3 ms, но FPS может упасть до 15-20 кадров. Тормоза вылазят периодически (в эти моменты тормозит вся анимация), из закономерностей заметил, что они часто появляются в периоды простоя (когда на сайте не совершается никаких действий 20-30 секунд).
Полагаю, возможная причина отчасти в самом железе/ПО (хотя оно шустрое), но хотелось бы устранить подвисания. Отсюда вопросы:
В чем причина подобных тормозов, кто сталкивался с этим? Какие решения Вы использовали, чтобы сделать анимацию более плавной?
P.S. "will-change: transform;" не сильно поможет, т.к. браузер и без него все выносит на отдельный слой.


Ответ

Добиться более плавной анимации помог комплекс следующих действий:
Точное указание property у transition (т.е. вместо "transition: all" указываем конкретное свойство с которым производится анимация). Использование при JS манипуляции с классами не classList, а className. Переход на это решение позволил добиться реального прогресса в плавности анимации. В частности, это решение подсказал VK, там используется такая же схема. Метод className входит в DOM Core (level 2), имеет практически полную совместимость со всеми браузерами, а также более эффективно обрабатывается браузерными движками с минимальными задержками.

sql вывести название категорий и посчитать количество товаров в данной категории

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

В базе данных имеются 2 таблицы

+Product |_id |_name |_category_id |_article

+Category |_id |_category_id |_name

Посчитать количество товаров - просто.
SELECT category_id as category, count(*) AS cnt FROM product GROUP BY category_id
В результате мы получим таблицу вида:

category: 1 2 3 4 5 ... в общем номера категорий cnt: ... количества товаров в категориях
Как мне сделать пересчет товаров и сопоставить колонку "category_id" таблицы product с колонкой "name" таблицы Category(названия категорий) в одном запроса?
Пробовал так:
SELECT category_id as category, count(*) AS cnt FROM product INNER JOIN category on product.category_id = category.category_id GROUP BY category_id
Пробовал так:
SELECT fid AS category, COUNT(*) AS cnt, cname FROM (SELECT product.category_id AS fid, category.name AS cname, category.id AS cid FROM category LEFT JOIN category on product.category_id = category.category_id) newtable GROUP BY cid, cname
В общем с SQL я не силен, буду рад любой помощи.

Ответ
SELECT category.name as category, count(*) AS cnt FROM product INNER JOIN category on product.category_id = category.category_id GROUP BY category.category_id


Ответ

Вот так должно все нормально работать:
SELECT c.name AS category, count(*) AS cnt FROM product AS p INNER JOIN category c ON p.category_id = c.category_id GROUP BY p.category_id
Мой результат:
"Category 01" => 2 "Category 02" => 3 "Category 03" => 4

Угол под 45 градусов у div

Друзья, может кто-то сталкивался с подобной задачей... Необходимо у div срезать углы (верхний-левый и нижний правый), под углом 45 градусов.
реализовал через clip-path
.corner45top { -webkit-clip-path: polygon(5% -200%, 100% 0%, 100% 100%, 0% 100%, 0% 100%, 0% 100%); clip-path: polygon(5% -200%, 100% 0%, 100% 100%, 0% 100%, 0% 100%, 0% 100%); clip-path: url("#swipe__clip-path"); background-color: #FFFFFF; box-shadow: 0 1px 6px 0 rgba(86,86,86,0.25); }
.corner45bottom { -webkit-clip-path: polygon(0 -100%, 100% 0%, 98% 100%, 0% 100%, 0% 100%, 0% 100%); clip-path: polygon(0 -100%, 100% 0%, 98% 100%, 0% 100%, 0% 100%, 0% 100%); clip-path: url("#swipe__clip-path-bottom"); background-color: #FFFFFF; box-shadow: 0 1px 0 0 rgba(86,86,86,0.25); }

Но все эти "красивости" никак не работают в браузере EDGE, есть ли какой-то простой вариант вылечить это? Мог бы сделать углы например картинкой, но за блоками есть background-image цветной(


Ответ

Для этого нам на помощь приходит SVG , подходит такой вариант ?

Применение CSS-свойств к элеметам внутри определенного div

На странице есть список внутри div, выглядящий примерно так:

  1. ...

Мне необходимо кастомизировать такой список, если он содержится в таком div, примерно таким способом:
ol { ... } ol li { ... } ol li:before { ... }
Как правильно описать это в файле стилей?


Ответ

Используйте в селекторе класс .wiki-content. Выглядеть это будет так:
.wiki-content ol { // Ваши стили }
.wiki-content li { // Ваши стили }
.wiki-content li:before { // Ваши стили }
Если у вас используется препроцессор, к примеру Less, можно сделать еще проще:
.wiki-content {
ol { // Ваши стили }
li { // Ваши стили &:before { // Ваши стили } } }

Реализация прироста ресурсов в реал-тайме в браузерной (мобильной) ММО стратегии

Как реализуют игровую механику в браузерных или мобильных ММО стратегий, на подобии марш империй, vikings, ikariam и.т.д, а точнее как им удается осуществлять прирост ресурсов в реал-тайме? Сервер запускается и обрабатывает каждую учетную запись прибавляя рассчитанное количество ресурсов в цикле каждую секунду?


Ответ

Могу предположить, что данные о приросте в секунду у каждого пользователя для каждого ресурса хранятся на их серверах.
Сервера мониторят последние таймстэмпы пользователей (от последнего совершенного действия, связанного с ресурсами, например, их трата, или заход\выход из приложения). Рассчитывается все по формуле (currentTimestamp - lastTimestamp) * RPS (Resources Per Second), а затем все это записывается в БД
А если пользователь находится в сессии постоянно, то этот прирост ресурсов просто "рисуется".
И когда юзер начинает с ними какое-то действие (Например, купил что-то и они потратились), сервер добавляет к прошлому значению ресурсов новые (по вышеупомянутой формуле) и уже изменяет значение ресурсов (Вычитает, или добавляет) и сохраняет в БД. Соот-но lastTimestamp присваивается currentTimestamp и так до следующего действия

Утечка памяти в TObjectList

Не могу найти решение для устранении утечки.

type TMyObj = class Caption: string; Description: string; Params:string; ParamsLst: TStringList;
public constructor Create(const aPath: string; const aParams: TStrings); overload; destructor Destroy(); override; end;
TDataList = class(TObjectList) public constructor Create; // function LoadFromINI(IniFile: TMemIniFile): boolean; function Remove(Obj: TMyObj): Integer; end;
var TObjData: TDataList;
implementation
constructor TMyObj.Create(const aPath: string; const aParams: TStrings); begin Caption := aParams.Values['Caption']; Description := aParams.Values['Description']; Params := aParams.Values['Params']; if aParams.Values['Params'] <> '' then begin ParamsLst := TStringList.Create; try ExtractStrings([';', ','], [' '], PChar(Params), ParamsLst); except ParamsLst := nil; end; end; end;
destructor TMyObj.Destroy; begin ParamsLst.Free; inherited; end;
constructor TDataList.Create; begin inherited Create; OwnsObjects := True; end;
function TDataList.Remove(Obj: TMyObj): Integer; begin Result := inherited Remove(Obj); end;
initialization TObjData := TDataList.Create;
finalization TObjData.Free;
заполнение TObjData, так
TObjData.Add(TMyObj.Create(sVal, SecParams));


Ответ

Код с учетом замечаний и предложений......
type TData = class private FCaption: string; FDescription: string; FParams: string; FParamsLst: TStringList; //.... public constructor Create(const aPath: string; const aParams: TStrings); destructor Destroy(); override; property Caption: string read FCaption; property Description: string read FDescription; property Params: string read FParams; property ParamsLst: TStringList read FParamsLst; //... end;
TDataList = class(TObjectList) private //... public constructor Create; destructor Destroy(); override; property //... end;
var DataList: TDataList;
implementation
{ TData } constructor TData.Create(const sPath: string; const sData: TStrings); begin Caption := aParams.Values['..']; Description := aParams.Values['..']; Params := aParams.Values['..']; if aParams.Values['..'] <> '' then begin ParamsLst := TStringList.Create; try ExtractStrings([','], [' '], PChar(Params), ParamsLst); except on E: Exception do ShowMessage(E.ClassName + ': ' + E.Message); end; end; end;
destructor TData.Destroy; begin inherited; end; { end TData }
{ DataList } constructor TDataList.Create; begin inherited Create; OwnsObjects := True; end;
destructor TDataList.Destroy; begin inherited; end; { end DataList }
Решение, проблемы ......
procedure TMain.FormDestroy(Sender: TObject); var I: Integer; begin // Удаление списков в объекте for i := 0 to DataList.Count - 1 do begin with DataList.Items[i] do begin ParamsLst.Free; end; end; // При удалении списка оставшиеся в нём объекты будут удалены. FreeAndNil(DataList); end;

Несколько результатов из БД, с учётом сортировки

Имеется таблица book в которой около 50 записей. Поля таблицы id(int),name(varchar),path(text),lang(int, value = 1,2,3). lang=1 примерно 18 записей lang=2 примерно 16 записей lang=3 примерно 16 записей Необходимо составить sql запрос, чтобы выбрать 3 книги, первая из которых это случайное число из первых 18 записей, второе это тоже случайное число из вторых 16 записей, и третья соответственно тоже случайное число из последних 16 записей
Что то на подобие такого: SELECT * FROM book WHERE lang=1 ORDER BY RAND () LIMIT 1 AND WHERE lang=2 ORDER BY RAND () LIMIT 1 AND WHERE lang=3 ORDER BY RAND () LIMIT 1;


Ответ

Для ваших объемов данных подойдет очень простой запрос:
SELECT random_book.* FROM book LEFT JOIN (SELECT * FROM book ORDER BY RAND()) random_book ON (book.lang = random_book.lang) GROUP BY random_book.lang
ORDER BY RAND() - это не быстро на больших обьемах данных.

Начальная страница браузера

Здравствуйте, уважаемые форумчане. Нужен совет, ну или помощь. Есть в каждом браузере начальные страницы. Ну или страницы часто посещаемых сайтов. При добавлении туда уже например яндекс или гугла, выглядит вот так просто, красиво. Хотелось бы для своего сайта, сделать красивое оформление на начальной странице. Но если честно я даже не представляю пока как запрос в гугл подать)) Подскажите куда рыть или, если не лень, то может на примере на простом объясните.


Ответ

Гуглить, наверное, так: express panel preview Хотя меня несколько настораживает, что результаты довольно старые.
В https://habrahabr.ru/post/115705 говорится
Можно просто добавить иконку размером не меньше чем 114*114:
Использовать медиа-запрос с view-mode
@media screen and (view-mode: minimized) { /* some styling of preview */ } Ответить на http-запрос, содержащий заголовок
X-Purpose: preview
соответствующим содержимым.

C#. Как преобразовать число с плавающей точкой в аналогичное число, но только с заданным количеством знаков после запятой?

Доброго времени суток!
Возник следующий вопрос: к примеру, у нас есть переменная типа double и некоторая точность (переменная precition), которая будет определять количество интересующих нас знаков после запятой:
double x = 9.3813020199999; double precition = 0.001;
Зная вышеперечисленные данные, нам нужно получить точное число 9.381 (и без лишних нулей в конце). Есть ли способ это осуществить?
UPD Мне необходимо протестировать метод Sqrt (код ниже) и я не знаю, как правильно написать тест для NUnit, если метод возвращает число double. Ведь у нас должно быть expected-значение, которое сравнивается с возвращаемым значением метода.
public static double Sqrt(double x, int n, double precition) { if (x < 0 && n % 2 == 0) throw new ArgumentException();
double result = x / n; double previousResult; do { previousResult = result; result = ((double)1 / n) * ((n - 1) * previousResult + (x / Sqr(previousResult, n - 1))); } while (Math.Abs(result - previousResult) > precition);
return result; }
Пока мой тестирующий метод, написанный с помощью NUnit, выглядит так:
[TestFixture] public class NewtonSqrtTests { [TestCase(4, 2, 0.001, ExpectedResult = 2.000)] [TestCase(27, 3, 0.0001, ExpectedResult = 3.0000)] [TestCase(88, 2, 0.001, ExpectedResult = 9.380)] [TestCase(81, 2, 0.001, ExpectedResult = 9.000)] public double Sqrt_PositiveTest(double x, int n, double precition) { return NewtonSqrt.Sqrt(x, n, precition); } }


Ответ

Если говорить о десятичных знаках, то оставаться в рамках типа double бессмысленно: в нём вы не можете выразить вашу требуемую точность точно. Например, потому, что в типе double нельзя точно выразить ни число 0.001, ни число 9.381. (иллюстрация, связанный ответ)
Вам нужно перейти к типу decimal, который специально для этого предназначен.
double x = 9.3813020199999; decimal precision = 0.001m; decimal result = Math.Round((decimal)x / precision) * precision; // 9.381
Если количество десятичных знаков известно в виде числа, можно проще:
double x = 9.3813020199999; decimal result = Math.Round((decimal)x, 3); // 9.381

Обновление: Если оставаться в рамках типа double, вы не можете их сравнивать: равенство теоретически одинаковых чисел типа double, вычисленных разными путями — практически невероятное событие из-за ошибок округления. В таких случаях используется примерное равенство с точностью до epsilon. Например, в NUnit есть для таких целей специальные функции
Values of type float and double are normally compared using a tolerance specified by the Within modifier.

C# Получить объект вызвавший getter свойства

Здравствуйте! У меня возникла проблема "красивого" способа изменения настроек "на лету". Наример:
private string _text; public string SampleTextProp { get { return _text; }
set { _text = value; } }
textBlock1.Text = SampleTextProp;
И вопрос: Есть ли возможность внутри геттера SampleTextProp получить объект textBlock1.Text, чтобы позже использовать его? В сеттере например. То есть мне нужно получить объект, который вызвал геттер. Надеюсь я понятно выразился... Спасибо большое! Update: Для чего мне это нужно. Есть класс хранящий в себе настройки для приложения представленные как свойства. По мере написания программы я применяю эти свойства к различным полям или свойствам других объектов. Но эти настройки будут применяться только при запуске программы, а мне надо видеть изменения во время исполнения. В тоже время я не хочу вручную связывать настройку и объект применяющий её (windowBorder.BorderThickness = Settings.Interface.BorderThickness.GetValue(windowBorder) или как-то так) Я хотел чтобы можно было просто вызвать свойство и всё. А класс его описывающий самостоятельно получил бы вызывающий объект, запомнил, и при последующем изменении свойства, автоматически применил новое значение ко всем ранее вызывавшим это свойство объектам. Фух


Ответ

То, что вам нужно, называется "дата-биндинг" (data binding, по русски - привязка данных) и идет рука об руку с шаблоном проектирования MVVM (Model - View - View Model).
Для WinForms это делается через вкладку свойств, далее - пункт (ApplicationSettings) для привязки настроек или пункт (DataBindings) для привязки источника данных.
В WPF это делается через указание в разметке конструкции {Binding}
BorderThickness="{Binding BorderThickness, Source={x:Static Settings.Default}}"
Если вы используете не стандартный класс настроек, а пишите свой - не забудьте реализовать интерфейс INotifyPropertyChanged

Как в Android Studio у существующего проекта поднять версию ОС устройства?

Добрый день, пишу в Android Studio под версию устройства Android 4 как можно в этом же проекте поднять версию до Android 6 ?


Ответ

Если имеется в виду минимальная поддерживаемая версия ОС, то укажите её в build.gradle (module app). Вам требуется изменить значение переменной minSdkVersion в блоке defaultConfig на 23

“Сапёр”. Алгоритм поиска соседних клеток, не содержащих мин или цифр

Стандартный "сапер". Поле 16 на 16 клеток. 20 мин на поле.
При первом нажатии игрок заведомо не попадает на клетку с миной. Он попадает либо на пустую клетку, либо на клетку, содержащую информацию о количестве мин вокруг. Назовем ее клеткой с цифрой.
Если игрок кликнул на клетку с цифрой - открываем только ее. Если игрок кликнул на полностью пустую клетку, то кроме этой самой клетки требуется открыть все (related, не могу перевод подобрать. Соединенные что ли) клетки включая те, которые содержат в себе цифру, но не дальше их. Что-то типа такого:

Игрок кликнул на зеленую точку. В красных содержатся мины. Желтые содержат в себе цифры. Фиолетовые отображают те клетки, которые должны быть открыты вместе с зеленой. (Да, на некоторых из желтых фиолетовые отметки неслучайны, те тоже должны быть открыты).
Собственно, интересует алгоритм поиска этих самых фиолетовых клеток Также, если есть какие-то тонкости реализации именно относительно JavaScript, то тоже буду рад выслушать.


Ответ

Самый простой алгоритм:
Если клетка пустая, проверить соседние клетки: слева, справа, сверху, снизу стоит обратить внимание на граничные случаю, как в примере в вопросе, когда нет клетки справа и снизу.
Если не пустая - ничего не делать.
Псевдокод
функция Проверить ячейку (ячейка) если ячейка проверерена -> выход если ячейка не пустая -> выход
Отметить, что ячейка проверена, чтобы не проверять дважды.
Проверить ячейку сверху если есть Проверить ячейку снизу если есть Проверить ячейку слева если есть Проверить ячейку справа если есть конец функции
Вариант без рекурсии:
функция Проверить ячейку (ячейку) если ячейка не пустая -> выход
получить ячейки для проверки <- [ ячейка сверху если есть ячейка снизу если есть ячейка слева если есть ячейка справа если есть ] // смежные
Пока есть ячейки для проверки:
если текущая ячейка пустая и не проверенная, то отметить ячейку как проверенную. удалить ее из списка ячеек для проверки. добавить в список ячеек для проверки смежные не проверенные ячейки
конец функции

C# и .Net. Почему пользовательская функция Swap работает неправильно?

Добрый вечер!
Задача следующая: Дан так называемый ступенчатый(зубчатый) массив целых чисел int[][] matrix. Для определенности, пусть массив будет размерности 5:
int[][] matrix = new int[5][] { new int[10] {5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, new int[4] {2, 2, 2, 2}, new int[5] {20, 20, 20, 20, 20}, new int[3] {1, 2, 1}, new int[4] { 2, 3, 4, 5 } }
Необходимо поменять две любые строки между собой. Для этого я написал следующую функцию Swap
///

/// Swapping matrix strings /// /// first string /// second string private static void SwapMatrixStrings(int[] a, int[] b) { int[] tmp = a; a = b; b = tmp; }
Казалось бы, что переменные типа int[] - это переменные ссылочного типа. Но почему тогда после вызова:
Swap(matrix[0], matrix[1]);
массив int[4] {2, 2, 2, 2} не поменялся местами с массивом int[10] {5, 5, 5, 5, 5, 5, 5, 5, 5, 5} в массиве matrix?
UPD. Если в методе передавать параметры по ссылке с помощью ключевого слова ref, то метод работает так, как надо.


Ответ

Потому что она обменивает локальные переменные, а не параметры. Параметры в C# передаются по значению, если не указано ref или out. Это относится и к параметрам ссылочного типа, при этом по значению передаётся ссылка
Попробуйте указать в сигнатуре функции ref

Что происходит в вашем коде? В функцию SwapMatrixStrings вы передали ссылочные выражения matrix[0] и matrix[1] в качестве аргументов. То есть, параметры a и b получили значение, совпадающее с matrix[0] и matrix[1] (то есть, их копии).
В результате выполнения вашей функции, значения a и b поменялись местами. Но это никак не затрагивает исходные величины matrix[0] и matrix[1]

Как проверить что class = “X” и заменить X на Y?

Всем привет, подскажите пожалуйста где ошибка
Суть в том что мне нужно проверить если class=like-r где id="colorlikreviews" , то заменить class=like-r на class=like-rs, если нет то указать class=like-r
if($("#colorlikreviews").className == 'like-r'){ document.getElementById("colorlikreviews").className = 'like-rs'; }else{ document.getElementById("colorlikreviews").className = 'like-r'; }


Ответ

if ($("#colorlikreviews").hasClass("like-r")) { $("#colorlikreviews").removeClass("like-r"); $("#colorlikreviews").addClass("like-rs"); } else { $("#colorlikreviews").addClass("like-r"); }
А ошибка, скорее всего, в id элемента: "colorlikereviews"
Update
Ух-ты! Оказывается, toggleClass хитрее, чем я думал.
function SwitchClass() { if ($("#colorlikreviews").hasClass("like-r")) { $("#colorlikreviews").toggleClass("like-r like-rs"); } else { $("#colorlikreviews").addClass("like-r"); } } .like-r { width:200px; height:200px; background:red; color:yellow; } .like-rs { width:200px; height:200px; background:green; }

AAA

Переход к якорю при заданном base

Можно ли в отдельно взятой ссылке тега отключить влияние ?
Например, в html-документе имеется тег , задающий корневой адрес сайта. Так вот, если на странице some.html я указываю
Если не писать путь к some.html, то придется использовать JS.
Anchor
Или так:
window.onload = function () { document.getElementById("anchor-test").addEventListener("click", function(e) { document.location.hash='test'; e.preventDefault(); }); }
https://stackoverflow.com/questions/8108836/make-anchor-links-refer-to-the-current-page-when-using-base

блоки try-catch. Обработка исключений

правильно ли я понимаю, что если первое закрытие выбросит ошибку, то остальные даже и не вызовутся? подскажите как ПРАВИЛЬНО исправить, а главное почему именно так!
private void closeStatement() throws DaoException, SQLException { try { getByIdStmt.close(); } catch (Exception e) { throw new DaoException("Error! getByIdStmt is not closed"); } try { updateStmt.close(); } catch (Exception e) { throw new DaoException("Error! updateStmt is not closed"); } try { addStmt.close(); } catch (Exception e) { throw new DaoException("Error! addStmt is not closed"); } try { deleteStmt.close(); } catch (Exception e) { throw new DaoException("Error! deleteStmt is not closed"); } System.out.println("Statement close"); }


Ответ

Возможно, так:
private void closeStatement() throws DaoException, SQLException { ArrayList err = new ArrayList(); try { getByIdStmt.close(); } catch (Exception e) { err.add("getByIdStmt"); } try { updateStmt.close(); } catch (Exception e) { err.add("updateStmt"); } try { addStmt.close(); } catch (Exception e) { err.add("addStmt"); } try { deleteStmt.close(); } catch (Exception e) { err.add("deleteStmt"); } if (!err.isEmpty()) { throw new DaoException("Error! "+String.join(", ", err)+" not closed"); } System.out.println("Statement close"); }
Поочерёдно пытаемся закрыть все statement, неудачи собираем. Потом выбрасываем общее для всех ошибок исключение.

Выделение памяти под константное свойство в классе

Имеется класс:
public class SomeClass { public SomeClass() { }
public const int SomeUsefulValue = 42; }
Создавая несколько (2 и более) экземпляров этого класса, память под константную переменную выделится один раз и переменная будет одна для каждого экземпляра? Или же для каждого экземпляра будет уникальная константная переменная?


Ответ

Констант нет.
Все упоминания константы будут заменены непосредственным значением при компиляции. Именно поэтому константы можно инициализировать только значениями, известными во время компиляции.
если смотреть с точки зрения языка, поведение const аналогично поведению static readonly, поэтому можно сказать, что константа одна на класс.

CSS свет с затухающим эффектом


Я нашел эту картину в Интернете, и хотел бы реализовать подобный эффект на моем сайте. Попытался сделать более темный фон, лампу разместить сверху, а картинку разместить под ней. Но я хочу, чтобы свет от лампы выглядел так, как будто он светится на картинке. Возможно ли это сделать?
Перевод вопроса: CSS light (fading)


Ответ

Вы можете использовать несколько псевдоэлементов для создания этого эффекта, включая linear gradient и transforms:
Демо [Наведите курсор на изображенние, чтобы увидеть этот эффект]
.light { position: relative; height: 300px; width: 300px; display: inline-block; margin-top: 20px; } .light img {/*Image inside*/ position: absolute; top: 0; left: 0; height: 100%; width: 100%; } .light:before {/*creates the bulb*/ content: ""; position: absolute; bottom: 100%;/*places above image*/ left: 50%; height: 20px; width: 100px; border-radius: 50%; background: lightgray; transform: translateX(-50%);/*places in center of image*/ z-index: 10;/*places in front of image*/ border: 2px solid dimgray;/*borders add 3D effect to bulb*/ border-bottom: none; border-top: 5px solid #222; } .light:after {/*creates the beam*/ content: ""; position: absolute; transition: all 0.4s; height: 0; width: 100px; top: -10px; left: 50%; transform: translateX(-50%) perspective(400px) rotateX(45deg);/*centers, makes as trapezium*/ transform-origin: top center; background: linear-gradient(0deg, transparent, rgba(255, 255, 255, 0.8));/*adds fading light*/ z-index: 5;/*places in front of image, but behind bulb*/ } .light:hover:after {/*demo only, add this to .light:after in production*/ height: 80%; }


Перевод ответа: CSS light (fading) effect @jbutler483

Почему исключения в асинхронном коде считаются необработанными?

Есть код скачивания файлов, на нижнем уровне есть простой цикл с ограничением, чтобы сделать несколько попыток скачивания, выглядит упрощенно вот так:
private static bool Failed = false;
static void Main(string[] args) { TaskScheduler.UnobservedTaskException += (o, a) => { throw a.Exception; }; ChapterDownload().Wait(); }
public static async Task ChapterDownload() { try { var pages = Enumerable.Range(0, 20); var pTasks = pages.Select(page => { return PageDownload() .ContinueWith(t => Console.WriteLine("{0}{1}", t.Status, t.IsFaulted)); }); await Task.WhenAll(pTasks.ToArray()); } catch (Exception ex) { // } }
public static async Task PageDownload() { if (Failed) throw new Exception("boom");
try { // var file = await new WebClient().DownloadDataTaskAsync(new Uri(@"http://example.com")); var file = await DownloadFile(new Uri(@"http://example.com")); if (file != null) throw new Exception("Restart download, downloaded file is corrupted"); } catch (Exception ex) { Failed = true; await PageDownload(); } }
public static async Task DownloadFile(Uri uri) { byte[] result; WebResponse response; var request = WebRequest.Create(uri);
try { response = await request.GetResponseAsync(); using (var memory = new MemoryStream()) { await response.GetResponseStream().CopyToAsync(memory); result = memory.ToArray(); } } catch (System.Exception ex) { return null; } if (response.ContentLength == result.LongLength) return result; return null; }
Проблема в чём - в текущем виде, происходит UnobservedTaskException, с текстовкой boom, т.е. явно моё. При этом, стоит мне заменить скачивание с самопала на webclient - UnobservedTaskException больше не возникает. В чём разница?


Ответ

Чтобы исключения задачи (Task) считались обработанными и не вызывали событие TaskScheduler.UnobservedTaskException необходимо их перевыбросить, например t.Result, t.Wait() или t.GetAwaiter().GetResult(), или просмотреть, обратившись с свойству Exception: t.Exception
В Вашем коде проблема возникает потому, что вы ждёте завершение не самих исходных задач, а их продолжений. В то время как продолжения не делают ничего, чтобы обработать исключения исходных задач. В результате исключения, возникшие в исходных задачах, остаются необработанными.

Как в WPF MVVM сделать привязку данных к ComboBox

Здравствуйте. Столкнулся с проблемой. Делаю приложение на WPF с использованием паттерна MVVM. Работу с базой данных осуществляю с помощью Entity Framework. Есть 2 таблицы: Сотрудники(ФИО, id должности) и Должности(id, название). Я хочу, чтобы на форме с сотрудниками, когда я выбираю одного из них, выводилась вся информация о нём (ФИО, должность и тд). Это я осуществил, создав класс EmployeesViewModel:
class EmployeesViewModel : INotifyPropertyChanged { OpticsEntities db; private Employee selectedEmployees; public ObservableCollection Employees { get; set; }
public Employee SelectedEmployees { get { return selectedEmployees; } set { selectedEmployees = value; OnPropertyChanged("SelectedEmployees"); } }
public EmployeesViewModel() { db = new OpticsEntities(); db.Employees.Load(); Employees = db.Employees.Local; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
private RelayCommand addCommand; private RelayCommand saveCommand; private RelayCommand removeCommand; private RelayCommand changeCommand;
public RelayCommand AddCommand { get { return addCommand ?? (addCommand = new RelayCommand(obj => { Employee employees = new Employee(); Employees.Insert(0, employees); SelectedEmployees = employees; })); } }
public RelayCommand SaveCommand { get { return saveCommand ?? (saveCommand = new RelayCommand(obj => { Employee employees = obj as Employee; if (employees != null) { db.Employees.Add(employees); db.SaveChanges(); } })); } }
public RelayCommand ChangeCommand { get { return changeCommand ?? (changeCommand = new RelayCommand(obj => { Employee employees = obj as Employee; if (employees != null) { var changeEmployees = db.Employees.Find(employees.id); employees = changeEmployees; db.SaveChanges(); } })); } } }
и представление:



Всё отлично работает. Можно добавить нового сотрудника и сохранить.
Но проблема вот в чем. Поле "Должность" связано с таблицей "Должности" по внешнему ключу (id). И я хочу, чтобы вместо текстового поля с id должности был ComboBox, в котором бы находились названия всех должностей из таблицы "Должности". По умолчанию в нем была бы та должность, которой соответствует сотрудник, но можно было бы открыть ComboBox и присвоить ему другую. После нажатия на Save всё сохранилось бы в базе.
Максимум, что я смог сделать, это создать ComboBox, в котором будут отображаться эти должности. Но для этого пришлось сделать еще одну коллекцию во ViewModel и обращаться уже к ней в ItemsSource. Естественно, что бы я в ней не выбрал, никакой связи с сотрудником не будет, так как данные не связаны получается.
Как мне сделать, чтобы в ComboBox отображались должности из таблицы Должности, и при выборе одной из них она бы присваивалась полю Должность у Сотрудника? Напомню, что таблицы связаны внешним ключом по id должности.


Ответ

Тут достаточно много вариантов реализации, красивых и не очень, но если попробовать сделать с участием дополнительной коллекции моделей представления для каждой должности, как вы описали.
Пример искусственный, написан для демонстрации подхода к использованию тонкостей привязки ComboBox к данным, ни в коем случае не является примером реализации правильного MVVM.
Модели сущностей предметной области:
public class Employee { public string Name { get; set; } public int PostID { get; set; } }
public class Post { public int ID { get; set; } public string Name { get; set; } }
Модели представления:
public class EmployeeViewModel : NotificationObject { public EmployeeViewModel(Employee model, IEnumerable posts) { Model = model; var postViewModels = new List(); foreach (var post in posts) { postViewModels.Add(new PostViewModel(post)); } PostViewModels = postViewModels; }
public Employee Model { get; set; } public IEnumerable PostViewModels { get; private set; } }
public class PostViewModel : NotificationObject { public PostViewModel(Post model) { Model = model; }
public Post Model { get; set; } }
Класс NotificationObject просто реализует INotifyPropertyChanged. В DataContext окна попадает EmployeeViewModel
Разметка:

Пример работающий, в Combobox будут отображаться названия должностей, при этом в объект Employee при выборе в ComboBox будет присваиваться валидный идентификатор должности.
У ComboBox есть несколько крайне полезных свойств.
DisplayMemberPath - путь к свойству сущности в DataContext элемента списка ComboBox, который будет отображаться в выпадающем списке и в основном теле ComboBox SelectedValue - наравне с SelectedItem можно биндиться к свойству SelectedValue, значение которого берётся по определённому пути из SelectedItem SelectedValuePath - путь от SelectedItem, по которому берётся SelectedValue
В моём примере при выборе в ComboBox в его свойство SelectedItem попадает PostViewModel, а в свойство SelectedValue попадает уже искомый идентификатор должности. Это свойство и забиндено на PostID сущности Employee
Надеюсь, принцип понятен и удастся перенести это на ваш случай.

Не отображается язык

Проблема следующая. На одних устройствах язык (Телугу) отображается (планшет Prestigio, samsung 6, в том числе на эмуляторах Genymotion), на другом устройстве нет (Alcatel One Touch, android 4.2.2). Причем в последнем устройстве длина невидимого текста определяется, текст место занимает, в лог (Android Studio) выводится.
Вывожу поддерживаемые устройством языки следующим образом -
for (Locale locale : Locale.getAvailableLocales()) { Log.i("LOCALE", locale.getLanguage() + "_" + locale.getCountry() + " [" + locale.getDisplayName() + "]"); }
Отстуствие языка "te" (Telugu) в этом списке не мешает отображению на экране, кроме Alcatel.
Как я понимаю проблема может всплыть не только в Alcatel-моделях, хотелось бы разобраться в причинах. В какую сторону глядеть, на что обратить внимание, что еще добавить к вопросу для ясности?
Интересно,можно ли программно определить, что шрифт не отображается, но длину/размер строки в представлении имеет?


Ответ

Вероятно, стандартный шрифт Алкателей не содержит нужных символов. Попробуйте включить в ваше приложение шрифт, который точно будет работать, и устанавливать его для отдельных представлений
someTextView.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/myfont.ttf"));
или для всего макета
public class FontChangeCrawler { private Typeface typeface;
public FontChangeCrawler(Typeface typeface) { this.typeface = typeface; }
public FontChangeCrawler(AssetManager assets, String assetsFontFileName) { typeface = Typeface.createFromAsset(assets, assetsFontFileName); }
public void replaceFonts(ViewGroup viewTree) { View child; for (int i = 0; i < viewTree.getChildCount(); ++i) { child = viewTree.getChildAt(i); if (child instanceof ViewGroup) { replaceFonts((ViewGroup)child); } else if (child instanceof TextView) { ((TextView) child).setTypeface(typeface); } } } }
public class MainActivity extends AppCompatActivity { @Override public void setContentView(View view) { super.setContentView(view);
FontChangeCrawler fontChanger = new FontChangeCrawler(getAssets(), "fonts/myfont.otf"); fontChanger.replaceFonts((ViewGroup)this.findViewById(android.R.id.content)); } }

GooglePlay отмена/отклонение платежа

Вопрос на понимание.
Продаю несколько приложений через GP (как платные приложения, так и контент). С завидной долей регулярности в "Управлении заказами" вижу статус "Платеж отклонен" или "Отмененные". В доках написано, что это возможно из-за разных причин (например нехватка денег, некорректный оператор и т.п.). Но некоторые покупатели пытаются совершить покупку по нескольку (до 8!) раз в разное время и она всё равно не проходит. Думаю, что люди достаточно сообразительны, чтобы хотя бы со второго раза уже положить деньги :)
Поэтому возможно причина отмен в чем-то другом? Возможно надо как-то по другому настроить публикацию приложения, внести изменения в код и т.п.?
Или, и другие публикующиеся разработчики меня поддержат, это нормальное явление - примерно 30% отклоненных платежей?


Ответ

Отмена платежа из-за добавочной стоимости. Сейчас во многих странах Google показывает цену без %налога. При оплате пользователь видит уже полную стоимость. У нас добавляется немного, в некоторых странах - весьма много. Это влияет на отказ Отмена платежа по ошибке. Сюда я сгруппировал все подобные варианты. Не буду рассматривать их по отдельности. Проблема прохождения транзакции. Как я понимаю, уже на уровне взаимодействия с банком. В некоторых случаях платёж не поступит несмотря на то, что пользователь получит программу. В некоторых случаях срабатывает родительский контроль, отменяющий оплату, произведенную ребенком и т.п. Программы-взломщики а ля "Freedom". Эти самые "8 раз", как правило, обусловлены ими.
Возможно, есть ещё варианты.
P.S. 30% - это не так уж и много :) Хотя всё зависит от цены и тематики (читай: аудитории).

Кнопки увеличиваются не в ту сторону.

Здравствуйте! Столкнулся с такой проблемой, когда кнопки стоят в один ряд, они увеличиваются вниз, мне нужно чтобы их увеличение происходило вверх, как исправить ошибку? Разметку прикрепляю ниже:
div.buttonsfooter { width: 350px; height: 45px; background: url(https://i.stack.imgur.com/TnnDv.png); background-size: 100%; background-repeat: no-repeat; border-radius: 5px; margin-top: 85px; margin-left: 1; transition: 0.3s; display: inline-block; position: relative; } div.buttonsfooter:hover { background: url(https://i.stack.imgur.com/TnnDv.png); margin-top: 65px; height: 65px; background-size: 100%; } a.buttontext { font-family: 'Open Sans', sans-serif; font-size: 1.000em; color: #fff; margin-top: 3%; margin-left: 28.5%; text-decoration: none; font-weight: bold; position: relative; display: inline-block; }



Ответ

display: inline-block; по-умолчанию имеют vertical-align: baseline; , стоит выровнять vertical-align: top; и обе кнопки вверх начинают увеличиваться:
div.buttonsfooter { width: 350px; height: 45px; background: url(https://dummyimage.com/600x400/333/fff); background-size: 100%; background-repeat: no-repeat; border-radius: 5px; margin-top: 85px; margin-left: 1; transition: 0.3s; display: inline-block; vertical-align: top; position: relative; } div.buttonsfooter:hover { background: url(https://dummyimage.com/600x400/ccc/fff); margin-top: 65px; height: 65px; background-size: 100%; } a.buttontext { font-family: 'Open Sans', sans-serif; font-size: 1.000em; color: #fff; margin-top: 3%; margin-left: 28.5%; text-decoration: none; font-weight: bold; position: relative; display: inline-block; }