Это невозможно.
Вы можете показать текстовое сообщение вместе с опцией для продолжения на странице или уйти.
Пожалуйста, просмотрите эту ссылку для получения дополнительной информации : https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
window.onbeforeunload = funcRef
funcRef
является ссылкой на функцию или выражение функции.- Функция должна назначить строковое значение для свойства
returnValue
объектаEvent
и вернуть ту же строку.Пример:
blockquote>window.onbeforeunload = function(e) { return 'Dialog text here.'; };
Вы можете после того, как пользователь решит остаться на странице, показать ваш модальный, но я думаю, что это предложение будет побеждено в то время.
Как заявили другие, вы можете перехватить навигацию, прослушивая клики и ключевые события в ссылках и формах на вашей странице, но это не позволит вам показывать какой-либо диалог, когда пользователь пытается ввести URL-адрес вручную, закрыть вкладку, закрыть окно, нажать на перезагрузку , кнопки назад или вперед и т. д.
Событие
beforeunload
создано таким образом, чтобы защитить пользователей от вредоносных скриптов.Если разрешено такое управление, кто-то может заблокировать ваш браузер в
Изменить.:
Мне удалось показать диалоговое окно подтверждения, которое работает почти так же, как вы хотите, присоединение к 2 событиям
beforeunload
иunload
. Он работает в Internet Explorer 11, Firefox 40 и Safari 5.1 для Windows (что я могу подтвердить прямо сейчас):
var alreadyTriggered = false; function onQuit() { if (alreadyTriggered) return true; alreadyTriggered = true; if (confirm('Sure?')) { alert('OK'); } else { alert('Cancel'); } } window.onbeforeunload = onQuit; window.onunload = onQuit;
You can reload the page to test it here.
Это зависит от перерыва в цикле событий JS, который вызывает диалог подтверждения, и нет возможности сделать эту работу с настраиваемыми диалогами, потому что страница изменится или закроется, прежде чем пользователи получат возможность взаимодействовать с ней.
До сих пор нет возможности избежать изменения страницы или закрытия страницы, а также не использовать эту функцию в Chrome. Это также не будет работать в Firefox, событие не было запущено взаимодействием с пользователем.
В Haskell легко определить функцию для этого:
matches x ps = foldl (||) False $ map (\ p -> p x) ps
Эта функция принимает список значений предикатов (типа a -> Bool
) и возвращает True
, если любой из предикаты соответствуют значению.
Это позволяет вам что-то вроде этого:
isMammal m = m `matches` [(=="Dog"), (=="Cat"), (=="Human")]
Приятно то, что это не должно быть просто равенством, вы можете использовать что-нибудь с правильным типом:
isAnimal a = a `matches` [isMammal, (=="Fish"), (=="Bird")]
Это может быть воспроизведено в Lua с помощью некоторой мета-магии: D
local function operator(func)
return setmetatable({},
{__sub = function(a, _)
return setmetatable({a},
{__sub = function(self, b)
return f(self[1], b)
end}
)
end}
)
end
local smartOr = operator(function(a, b)
for i = 1, #b do
if a == b[i] then
return true
end
end
return false
end)
local isPrimaryColor = someColor -smartOr- {"Red", "Blue", "Either"}
Примечание: Вы можете изменить имя -smartOr- на что-то вроде -isEither-, чтобы сделать его еще БОЛЬШЕ читаемым. ]
Последние примеры, которые вы приводите, являются, по сути, синтаксическим сахаром, они должны будут оценивать тот же код, что и более длинная форма, поскольку в какой-то момент исполняемый код должен сравнивать ваше значение с каждым из условий по очереди.
Синтаксис сравнения массивов, приведенный здесь в нескольких формах, ближе, и я подозреваю, что есть другие языки, которые становятся еще ближе.
Основная проблема с приближением синтаксиса к естественному языку состоит в том, что последний не просто неоднозначный, он ужасно неоднозначный. Даже при минимальной неопределенности нам все-таки удается вносить ошибки в наши приложения. Можете ли вы представить, на что это было бы похоже, если бы вы программировали на естественном английском языке?!
Языки на компьютерах сравниваются как двоичные, потому что все они предназначены для машины, которая использует двоичные данные для представления информации. Они были разработаны с использованием схожей логики и с похожими целями. Английский язык не был разработан логически, предназначен для описания алгоритмов, а человеческий мозг (аппаратное обеспечение, на котором он работает) не основан на двоичном коде. Это инструменты, предназначенные для различных задач.
Просто добавить в примеры языков
Схема
(define (isPrimaryColor color)
(cond ((member color '(red blue yellow)) #t)
(else #f)))
(define (someNumberTest x)
(cond ((or (and (>= x 1) (<= x 100)) (and (>= x 10000 (<= x 2000))) #t)
(else #f)))
Две возможности
Java
boolean isPrimary = Arrays.asList("red", "blue", "yellow").contains(someColor);
Python
a = 1500
if 1 < a < 10 or 1000 < a < 2000:
print "In range"
Это потому, что языки программирования находятся под влиянием математики, логики и теории множеств в частности. Булева алгебра определяет операторы ∧, ∨ таким образом, что они не работают как разговорный естественный язык. Ваш пример будет записан так:
Let p(x) be unary relation which holds if and only if x is a primary color
p(x) ⇔ r(x) ∨ g(x) ∨ b(x)
or
p(x) ⇔ (x=red) ∨ (x=green) ∨ (x=blue)
Как вы видите, он очень похож на нотацию, которая будет использоваться в языке программирования. Поскольку математика обеспечивает прочные теоретические основы, языки программирования основаны на математике, а не на естественном языке, который всегда оставляет много места для интерпретации.
РЕДАКТИРОВАТЬ: Вышеприведенное утверждение можно упростить, используя обозначение набора:
p(x) ⇔ x ∈ {red, green, blue}
, и действительно, некоторые языки программирования, в особенности Паскаль, включают в себя множество, так что вы можете набрать:
type
color = (red, green, blue, yellow, cyan, magenta, black, white);
function is_primary (x : color) : boolean;
begin
is_primary := x in [red, green, blue]
end
Но наборы в качестве языковой функции не завоевали популярность.
PS. Извините за мой несовершенный английский.
Как математик, я бы сказал, что цвет является основным в том и только в том случае, если он является членом набора {красных, зеленых, синих} основных цветов.
И это именно то, что вы могли бы сказать в Delphi:
isPrimary := Colour in [clRed, clGreen, clBlue]
На самом деле, я использую эту технику очень часто. В прошлый раз было три дня назад. Реализуя свой собственный интерпретатор языка сценариев, я написал
const
LOOPS = [pntRepeat, pntDoWhile, pntFor];
, а затем в несколько строк
if Nodes[x].Type in LOOPS then
@supercat, и т.д. («Что касается того, почему никто этого не сделал, я не знаю».):
Вероятно, потому, что разработчики языков программирования - математики (или, по крайней мере, математически склонные). Если математику нужно установить равенство двух объектов, она естественным образом скажет
X = Y,
. Но если X может быть одной из множества вещей A, B, C, ..., тогда она определит набор S = {A, B, C, ...}
этих вещей и напишет
X ∈ S.
Действительно, это чрезвычайно распространено, что вы (математики) пишете X ∈ S
, где S - это множество
S = {x ∈ D; P(x)}
объектов в некоторой вселенной D, обладающих свойством P, вместо записи P(X)
. Например, вместо того, чтобы сказать «x является положительным действительным числом» или «PositiveReal (x)», можно сказать x ∈ ℝ⁺
.
Мне вспоминается, когда я впервые начал изучать программирование на языке Basic, и в какой-то момент я написал
if X=3 OR 4
Я намеревался сделать это так, как вы описываете, если X равен 3 или 4. Компилятор интерпретировал это как:
if (X=3) OR (4)
То есть, если X = 3 верно, или если 4 верно. Так как он определил все ненулевое значение как истинное, 4 - это истина, все ИЛИ ИСТИНА - это истина, и поэтому выражение всегда было истинным. Я потратил много времени на то, чтобы понять это.
Я не утверждаю, что это что-то добавляет к обсуждению. Я просто подумал, что это может быть слегка забавный анекдот.
Вопрос обоснованный, и я бы не стал считать это изменение синтаксическим сахаром. Если сравниваемое значение является результатом вычислений, было бы лучше сказать:
if (someComplicatedExpression ?== 1 : 2 : 3 : 5)
, чем сказать
int temp; temp = someComplicatedExpression; if (temp == 1 || temp == 2 || temp == 3 || temp == 5)
, особенно если не было никакой другой необходимости для временной переменной обсуждаемый. Современный компилятор мог бы, вероятно, распознать короткое полезное время жизни «temp» и оптимизировать его для регистра, и, вероятно, мог бы распознать шаблон «посмотрим, является ли переменная одной из определенных констант», но не было бы вреда, если бы программист сохранить компилятор проблемы. Указанный синтаксис не будет компилироваться на любом существующем компиляторе, но я не думаю, что он будет более двусмысленным, чем (a + b >> c + d), чье поведение определено в спецификации языка.
Что касается того, почему никто этого не сделал, я не знаю.
Иконка содержит объект, который вы описываете.
if y < (x | 5) then write("y=", y)
Мне скорее нравится этот аспект Icon.
В Perl 6 вы можете сделать это с помощью соединений :
if $color eq 'Red'|'Blue'|'Green' {
doit()
}
В качестве альтернативы вы можете сделать это с помощью оператора интеллектуального сопоставления (~~
). Следующее примерно эквивалентно синтаксису if value in list:
в Python, за исключением того, что ~~
делает намного больше в других контекстах.
if ($color ~~ qw/Red Blue Green/) {
doit()
}
Парены также делают его действительным perl 5 (> = 5.10); в Perl 6 они необязательны.
Вам понравится Perl 6 , потому что он имеет:
(1 <= $someNumber <= 100) || (1000 <= $someNumber <= 2000))
$isPrimaryColor = $someColor ~~ "Red" | "Blue" | "Yellow"
И вы можете комбинировать оба диапазона:
$someNumber ~~ (1..100) | (1000..2000)
В C #:
if ("A".IsIn("A", "B", "C"))
{
}
if (myColor.IsIn(colors))
{
}
Использование этих расширений:
public static class ObjectExtenstions
{
public static bool IsIn(this object obj, params object [] list)
{
foreach (var item in list)
{
if (obj == item)
{
return true;
}
}
return false;
}
public static bool IsIn<T>(this T obj, ICollection<T> list)
{
return list.Contains(obj);
}
public static bool IsIn<T>(this T obj, IEnumerable<T> list)
{
foreach (var item in list)
{
if (obj == item)
{
return true;
}
}
return false;
}
}
Я думаю, что большинство людей считают что-то вроде
isPrimaryColor = ["Red", "Blue", "Yellow"].contains(someColor)
достаточно ясным, что им не нужен дополнительный синтаксис для этого.
Python на самом деле дает вам возможность делать последние вещи довольно хорошо:
COBOL использует уровни 88
для реализации именованных значений, именованных групп значений и именованных диапазонов значений.
Например:
01 COLOUR PIC X(10).
88 IS-PRIMARY-COLOUR VALUE 'Red', 'Blue', 'Yellow'.
...
MOVE 'Blue' TO COLOUR
IF IS-PRIMARY-COLOUR
DISPLAY 'This is a primary colour'
END-IF
Тесты на дальность охватываются следующим образом:
01 SOME-NUMBER PIC S9(4) BINARY.
88 IS-LESS-THAN-ZERO VALUE -9999 THRU -1.
88 IS-ZERO VALUE ZERO.
88 IS-GREATER-THAN-ZERO VALUE 1 THRU 9999.
...
MOVE +358 TO SOME-NUMBER
EVALUATE TRUE
WHEN IS-LESS-THAN-ZERO
DISPLAY 'Negative Number'
WHEN IS-ZERO
DISPLAY 'Zero'
WHEN IS-GREATER-THAN-ZERO
DISPLAY 'Positive Number'
WHEN OTHER
DISPLAY 'How the heck did this happen!'
END-EVALUATE
Я думаю, все это произошло, потому что COBOL должен был подражать английскому в некоторой степени.
x > 0 and x < y
), пока разработчики языка не удосужились поддержать общую форму в математике, (0 < x < y
).
В большинстве языков оператор сравнения возвращает логический тип. В случае 0 < x < y
, если это интерпретировать как (0 < x) < y
, это было бы бессмысленно, поскольку <
не имеет смысла сравнивать булевы значения. Следовательно, новый компилятор может интерпретировать 0 < x < y
как tmp:=x, 0 < tmp && tmp < y
без нарушения обратной совместимости. Однако в случае x == y == z
, если переменные уже являются булевыми значениями, неясно, означает ли это x == y && y == z
или (x == y) == z
.
В C # я использую следующий метод расширения, чтобы вы могли написать someColor.IsOneOf("Red", "Blue", "Yellow"
). Это менее эффективно, чем прямое сравнение (как в случае с массивом, циклом, вызовами Equals()
и боксом, если T
является типом значения), но это, безусловно, удобно.
public static bool IsOneOf<T>(this T value, params T[] set)
{
object value2 = value;
for (int i = 0; i < set.Length; i++)
if (set[i].Equals(value2))
return true;
return false;
}
Вам придется немного пройти уровень абстракции, чтобы выяснить причину. Инструкции сравнения / перехода в x86 являются двоичными (так как они могут быть легко вычислены за несколько тактов), и так оно и было.
Если хотите, многие языки предлагают абстракцию для этого. В PHP, например, вы можете использовать:
$isPrimaryColor = in_array($someColor, array('Red', 'White', 'Blue'));
В Python вы можете сказать ...
isPrimaryColor = someColor in ('Red', 'Blue', 'Yellow')
... который я нахожу более читабельным, чем ваш синтаксис (== "Red" or == "Blue")
. Есть несколько причин для добавления поддержки синтаксиса для языковой функции:
someNumber (> 1 and < 10)
) это может быть более полезным, но даже тогда это не приносит вам большой выгоды (а Python позволяет вам сказать 1 < someNumber < 10
, что еще яснее). Так что не ясно, предложенные изменения особенно полезны.
В python вы можете сделать что-то вроде этого:
color = "green"
if color in ["red", "green", "blue"]:
print 'Yay'
Он называется оператором in
, который проверяет членство в наборе.
Я пока не вижу ответа Objective-C. Вот один из них:
BOOL isPRimaryColour = [[NSSet setWithObjects: @"red", @"green", @"blue", nil] containsObject: someColour];
irb(main):023:0> %w{red green blue}.include? "red"
=> true
irb(main):024:0> %w{red green blue}.include? "black"
=> false
irb(main):008:0> def is_valid_num(x)
irb(main):009:1> case x
irb(main):010:2> when 1..100, 1000..2000 then true
irb(main):011:2> else false
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> is_valid_num(1)
=> true
irb(main):015:0> is_valid_num(100)
=> true
irb(main):016:0> is_valid_num(101)
=> false
irb(main):017:0> is_valid_num(1050)
=> true
Пока никто не упомянул SQL. Он имеет то, что вы предлагаете:
SELECT
employee_id
FROM
employee
WHERE
hire_date BETWEEN '2009-01-01' AND '2010-01-01' -- range of values
AND employment_type IN ('C', 'S', 'H', 'T') -- list of values