window.close та self.close не закривають вікно в Chrome


174

Проблема полягає в тому, що коли я викликаю window.close()або self.close()він не закриває вікно. Зараз, здається, існує думка, що в Chrome ви не можете закрити за скриптом жодне вікно, яке не створено скриптом. Це явно неправдиво, але незалежно від того, як передбачається, все-таки це робити, навіть якщо для підтвердження потрібне спливаюче повідомлення. Цього не відбувається.

Так само хто - небудь є реальний, функціональний і перевірений метод закриття вікна , використовуючи щось на зразок javascript:window.close()або javascript:self.close()що на насправді робить те , що , як очікується , і то , що відбувається як раз відмінно в будь-якому браузері , який не грунтується на Chrome? Будь-які пропозиції будуть дуже вдячні, і я шукаю специфічне рішення для Javascript, нічого JQuery чи реалізація сторонніх розробників.

Оновлення: Хоча більшість запропонованих пропозицій має серйозні обмеження та проблеми з юзабіліті, остання пропозиція (специфічна для TamperMonkey), що використовується // @grant window.closeв заголовку сценарію, часто виконуватиме трюк навіть на тих вкладках, які зазвичай не можуть впоратися із методом закриття. Хоча це не зовсім ідеально і не узагальнюється до кожного випадку, але в моєму випадку це гарне рішення.


window.close()працює для мене в хромі.
пюре

3
@ GµårÐïåñ: Гм, ні, це не так. Це не має нічого спільного з мовою. Це функція, реалізована браузерами. Якщо ви можете написати мінімальний приклад, який показує, як window.closeне працює так, як слід, я думаю, що це може бути кориснішим, ніж сказати: "це не працює".
Блендер

3
Я наводив вам ДВОХ прикладів. <a href="javascript:window.close">CLOSE</a>
Прописавши

3
опікун, що неправильний JavaScript. Спробуйте window.close (), і він працює. window.close - це лише назва змінної, і вона не буде викликати функцію (принаймні, це не так, коли я перевіряю її в chrome 37). Коли я зміню ваш приклад на window.close (), він працює в chrome 37.
Джордж

3
GµårÐïåñ Те, що сказав @George, НЕ суперечить (якщо я зовсім не зрозумів значення цього слова). Він вірно стверджує, що у ваших прикладах є синтаксична помилка javascript у ваших прикладах, і якщо у вашому коді програми є однакові помилки, то це, швидше за все, причина вашої проблеми. Якщо, однак, це лише помилки у ваших прикладах, то вам слід виправити ці помилки, щоб отримати кращі відповіді.
Superole

Відповіді:


187

Звичайний javascript не може закрити вільно-невільно. Це функція безпеки, запроваджена деякий час тому, щоб зупинити різні шкідливі подвиги та роздратування.

З останньої робочої характеристики дляwindow.close() :

close()Метод на Window об'єкти повинні, якщо всі наступні умови, близько контекст перегляду :

  • Відповідний контекст перегляду A доступний для скриптів .
  • Контекст перегляду поточного сценарію знайомий з контекстом A перегляду .
  • Перегляду контексту сценарію чинного дозволено переміщатися контекстним перегляд A .

Контекст перегляду доступний для скриптів, якщо це допоміжний контекст перегляду, створений сценарієм (на відміну від дії користувача), або якщо це контекст перегляду, історія сеансів містить лише один документ.

Це означає, що за одним невеликим винятком, JavaScript не повинен дозволяти закривати вікно, яке не було відкрито тим самим JavaScript.

Chrome допускає цей виняток - який не застосовується до сценаріїв користувачів - однак Firefox цього не робить. У програмі реалізації Firefox викладено :

Цей метод дозволяється викликати лише для Windows, які були відкриті скриптом за допомогою window.openметоду.


Якщо ви спробуєте скористатись window.closeGreasemonkey / Tampermonkey / usercript, ви отримаєте:
Firefox: Повідомлення про помилку, " Scripts may not close windows that were not opened by script."
Chrome: просто мовчки виходить з ладу.



Довгострокове рішення:

Найкращий спосіб вирішити це - замість цього зробити розширення Chrome та / або Firefox. Вони можуть надійно закрити поточне вікно.

Однак оскільки ризики для безпеки, спричинені window.close, значно менші для сценарію Greasemonkey / Tampermonkey; Greasemonkey і Tampermonkey можуть розумно надати цю функціональність у своєму API (по суті, пакуючи розширення для вас).
Розгляньте запит на функцію.



Гакітний спосіб вирішення:

Зараз Chrome є вразливим до подвигу "самонаправлення". Отже, такий код використовувався для роботи в цілому:

open(location, '_self').close();

Така поведінка баггі, IMO, і зараз (станом на приблизно квітня 2015 року) здебільшого заблокована. Він все одно працюватиме з введеного коду, лише якщо вкладка свіжо відкрита і не має сторінок в історії перегляду. Тож корисно лише у дуже малій кількості обставин.

Однак варіація все ще працює на Chrome (v43 та v44) плюс Tampermonkey (v3.11 або новішої версії) . Використовуйте явне @grantта зрозуміле window.close(). EG:

// ==UserScript==
// @name        window.close demo
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @grant       GM_addStyle
// ==/UserScript==

setTimeout (window.close, 5000);

Дякуємо zanetu за оновлення. Зауважте, що це не працюватиме, якщо відкрита лише одна вкладка. Це лише закриває додаткові вкладки.


Firefox захищений від цього подвигу. Отже, єдиний спосіб JavaScript - калічити параметри безпеки, один браузер за один раз.

Ви можете відкрити about:configі встановити
allow_scripts_to_close_windowsв true.

Якщо ваш сценарій призначений для особистого використання, продовжуйте це робити. Якщо ви попросите когось іншого ввімкнути це налаштування, вони були б розумними та виправданими, щоб відмовитися від забобонів.

Наразі для Chrome немає еквівалентних налаштувань.


3
Гей, друже мій, радий нарешті почутись від тебе. Лише зауважте, на Fx ви можете обійти це обмеження, перевернувши dom.allow_scripts_to_close_windows;falseна, trueале я не здогадуюсь нічого в Chrome, не зламаючи джерело / перебудову, як я зараз його обійшов . Я знаю і говорив з розробником TM, і в недавній альфа-беті ми поставили це як варіант сумісності (налаштування сценарію) для роботи в стилі man-in-mid. Думаю, окрім хакі у нас немає чистого рішення, шкода.
GµårÐïåñ

3
Якщо у когось виникають проблеми з window.close або певною різницею поведінки серед браузерів, уважно прочитайте цю відповідь - вона дійсно має всю потрібну інформацію.
Брон Девіс

Чи є спосіб перевірити, чи вікно було відкрито сценарієм чи ні? (Мені потрібно показати / приховати кнопку назад, не хочу використовувати хак) Спасибі EDIT: window.opener === null
Cétia

Оскільки Chrome 36.0.1985.125 ВЕРЕДНЯ, 16 липня 2014 року, хакі обхідні шляхи можуть не працювати, детально у моїй відповіді.
swcool

2
window.close()буде працювати в Tampermonkey, якщо встановлено @grantінше значення, ніж none. Дивіться цю нитку .
zanetu

32

Chrome Виправлено проблеми безпеки у версії 36.0.1985.125

Chrome 36.0.1985.125 СЕРЕДА, 16 липня 2014 року Примітка до випуску

З мого спостереження, це оновлення вирішило проблему використання window.close()для закриття спливаючого вікна. Це ви побачите на консолі, коли не вдасться, "Сценарії можуть закрити лише ті вікна, які були відкриті нею". Це означає, що шалені шляхи (відповідь Брока Адамса) можуть не спрацювати в останньому випуску .

Так, у попередніх версіях Chrome, випущених нижче, блок коду нижче може працювати, але не з цим оновленням.

window.open('', '_self', '');
window.close();

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

chrome.windows.remove(integer windowId, function callback)

метод її видалення. API розширення Windows для Chrome можна знайти на chrome.windows .

Насправді моє хромоване розширення MarkView зіткнулося з цією проблемою, і мені довелося оновити свій код, щоб він працював для цього оновлення Chrome. До речі, MarkView - це інструмент для читання та запису дивовижних файлів відмітки, він пропонує функції, включаючи контур контенту, таблиці сортування та виділення синтаксису блоку коду з номером рядка.

Я також створив цю публікацію , будь-які коментарі вітаються.


2
Правильний злом open(location, '_self').close();- відзначте використання повернутого значення з open(). Це все ще працює на Chrome36.0.1985.125 m
Brock Adams

У моєму випадку, я просто тестую ще раз open(location, '_self').close();, я отримав "Несанкціоновану" помилку на цьому. Ця помилка відрізняється від 'window.close () (warning on this"Scripts may close only the windows that were opened by it."). It looked like open (location,' _self '). Close (); `трохи рухається вперед, але в моєму випадку вона не може завершитися. Дякуємо @ brock-adams за коментар.
swcool

У мене є машинопис, і коли я кажу, chrome.windows.removeвін не міг знайти символ хрому. як я можу це вирішити? мені потрібно додати якусь посилання?
DevT

@devt chrome.windows.remove - це розширення API для Chrome, ваш JavaScript повинен розпізнаватися вашою програмою розширення хрому. Ви можете спробувати його у background.js, у вашому хромовому розширенні manifest.json, вам потрібно мати: "background": {"scriptpts": ["background.js"], ...},
swcool

Я видалив функцію входу в MarkView, щоб користувачі могли вільно отримувати доступ. Тож приклад, про який я згадував вище, зараз недоступний.
swcool

21

У tampermonkey тепер ви можете використовувати

// @grant        window.close

А потім просто подзвоніть

window.close();

Я підтвердив, що це спрацьовує в багатьох випадках, але все ж час від часу вперті, але краще, ніж нічого, дякую. Я додам його до посади.
GµårÐïåñ

2
Як зауваження: не працює для мене в Greasemonkey 3.10
mt025

17

Я використовую метод, розміщений Brock Adams, і він навіть працює у Firefox, якщо його ініціює користувач.

open(location, '_self').close();

Я закликаю це з натискання кнопки, щоб його було ініційовано користувачем , і він все ще працює чудово за допомогою Chrome 35-40, Internet Explorer 11, Safari 7-8 та ТАКОЖ Firefox 29-35. Я тестував, використовуючи версії 8.1 Windows та Mac OS X 10.6, 10.9 та 10.10, якщо це інше.


Самозакриваючий віконний код (на сторінці, що закривається)

Повний код, який буде використовуватися у відкритому користувачем вікні, яке може закрити себе:

window_to_close.htm

JavaScript:

function quitBox(cmd)
{   
    if (cmd=='quit')
    {
        open(location, '_self').close();
    }   
    return false;   
}

HTML:

<input type="button" name="Quit" id="Quit" value="Quit" onclick="return quitBox('quit');" />

Спробуйте цю тестову сторінку: (Зараз тестується в Chrome 40 та Firefox 35)

http://browserstrangeness.bitbucket.io/window_close_tester.htm


Код відкривача вікон (на сторінці, що відкриває вищевказану сторінку)

Щоб зробити цю роботу, сумісна міжбірна браузерна сумісність вимагає, щоб вікно, яке слід закрити, повинно бути вже відкрито користувачем, натиснувши кнопку в межах одного домену сайту.

Наприклад, вікно, яке використовує метод вище, щоб закрити себе, можна відкрити зі сторінки за допомогою цього коду (код, наданий із моєї сторінки прикладу, пов'язаної вище):

window_close_tester.htm

JavaScript:

function open_a_window() 
{
    window.open("window_to_close.htm"); 

    return false;
}

HTML:

<input type="button" onclick="return open_a_window();" value="Open New Window/Tab" />

Забули про винятки, ініційовані користувачем; хороший улов. Я думаю, що більшість користувачів абонентів хочуть повністю автоматичної роботи. Вони вже мають зручний механізм закриття, ініційований користувачем - той маленький X у верхньому правому куті. (^_^)
Брок Адамс

1
Так чи інакше, це не працює для мене. Ні на Firefox 30, ні на Chrome 37. Все, що він робить, це зробити сторінку порожньою (дійсно дивна поведінка). Мій код є <button onclick="open(location,'_self').close()" >Close Window</button>. Чи роблю я щось явно не так? Мені здається, це також ініціюється користувачем. Зауважте, що я отримую такий же результат, якщо використовую a <button>або an <input type="button">.
LordOfThePigs

Вище додано тестову сторінку у відповідь.
Джефф Клейтон

@YumYumYum дякую за допис, нещодавно bitbucket.org змінив посилання на bitbucket.io - зафіксував у відповіді зараз
Джефф Клейтон

Для мене це працює (мати кнопку на сторінці, щоб закрити вікно). Те, що не вийшло, window.open('', '_self', ''); window.close(); але працювало з open(location, '_self').close();
krystonen

10

Багато людей все ще намагаються знайти спосіб закрити браузер Chrome за допомогою JavaScript. Наступний метод працює лише тоді, коли ви використовуєте Chrome, наприклад, як запуск програми APP - кіоск!

Я перевірив наступне:

Я використовую таке розширення: Закрити кіоск

Я дотримуюся інструкцій із використання, і, здається, він працює добре (переконайтеся, що ви очищаєте кеш, роблячи тести). Я використовую JavaScript (додається для події клацання):

window.location.href = '/closekiosk';

Я сподіваюся, що це комусь допоможе, оскільки це єдине діюче рішення, яке я знайшов.

Примітка. Здається, розширення працює у фоновому режимі і додає значок лотка Chrome. У ньому встановлено наступний параметр: "Нехай Chrome працює у фоновому режимі" (або подібний текст). Можливо, вам доведеться пограти з ним, поки це не допоможе вам. Я це зняв, і тепер він працює просто чудово!


9

Незважаючи на те, що це "очевидно помилково", те, що ви говорите "здається, є вірою", насправді правильне. У документації Mozilla на window.close йдеться

Цей метод дозволяється викликати лише для Windows, які були відкриті скриптом методом window.open. Якщо вікно не було відкрито скриптом, на консолі JavaScript з'являється така помилка: Сценарії можуть не закривати вікна, які не були відкриті скриптом

Ви кажете, що це "все-таки повинно робити це", але я не думаю, що ви знайдете будь-яку посилання, яка це підтверджує, можливо, ви щось неправильно згадали?


9

Я знайшов новий спосіб, який працює для мене перфектно

var win = window.open("about:blank", "_self");
win.close();

1
це 2017 рік, і я все ще отримую помилку "Сценарії можуть не закривати вікна, які не були відкриті скриптом".
Ротімі

Гарний злом для кнопки підтвердження IE 11.
Gopal00005

Працює на Chrome і Firefox
Vineeth Pradhan

1
Схоже, ця дірка була заповнена. Я не знаю, коли, але я використовую останню версію 84.x. Порожня сторінка завантажується, але закриття не працює.
Скотт Крістенсен

4

Наведений нижче код працював для мене -

window.open('location', '_self', '');
window.close();

Тестовано на Chrome 43.0.2357.81


Чи можете ви, будь ласка, додати версію Chrome?
Стефан

Моя хромована версія - 43.0.2357.81.
DfrDkn

7
Для мене, що просто замінює поточне вікно, вікно в / location.
alianos-

@ alianos- для мене теж.
Рікардо Гонзалес

1
Не працює в останньому хромі - Версія 61.0.3163.100 (Офіційна збірка) (64-розрядна)
Subhajit

1

Це може бути старим, але давайте відповімо на це.

Я використовую top.close (), щоб закрити вкладку. window.close () або інший відкритий ... закрити не працював для мене.


11
Це також страждає від "Scripts may not close windows that were not opened by script."проблеми, згаданої в інших відповідях.
kad81

1
будь ласка, дайте рішення щодо вашої відповіді. будь ласка, не обговорюйте проблему лише у своїй відповіді.
Bimal Das

0

У моєму випадку сторінку потрібно було закрити, але, можливо, вона була відкрита посиланням і, таким чином, window.closeне вдасться.

Я вирішив вирішити проблему - випустити window.closeта послідовно window.setTimeoutперенаправляти на іншу сторінку.

Таким чином, якщо це window.closeвдасться, виконання на цій сторінці зупиняється, але якщо воно не вдалося, через секунду воно перенаправить на іншу сторінку.

window.close();
window.setTimeout(function(){location.href = '/some-page.php';},1000);

0

Ця відповідь від Брока зрозуміла, що вона працювала на мене. JavaScript не повинен дозволяти закривати вікно, яке не було відкрито тим самим JavaScript.

Я можу закрити дочірнє вікно лише в тому випадку, якщо я закрию його від батьківського JavaScript. тож у своєму батьків я можу зробити щось подібне.

var myChildWindow;

function openWindow(){
myChildWindow = window.open("","myChildWindow","width=400,height=400");
}

function closeWindow() {
myChildWindow.close();
}

-1

Ви також можете спробувати використовувати мій код нижче. Це також допоможе вам перенаправити батьківське вікно:

Батько:

<script language="javascript">

function open_a_window() 
{
    var w = 200;
        var h = 200;
        var left = Number((screen.width/2)-(w/2));
        var tops = Number((screen.height/2)-(h/2));

        window.open("window_to_close.html", '', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+tops+', left='+left);

   return false;
}

// opener:
window.onmessage = function (e) {
  if (e.data === 'location') {
    window.location.replace('https://www.google.com');
  }
};

</script>

<input type="button" onclick="return open_a_window();" value="Open New Window/Tab" />

Вискочити:

<!DOCTYPE html>
<html>
<body onload="quitBox('quit');">

<h1>The window closer:</h1>

<input type="button" onclick="return quitBox('quit');" value="Close This Window/Tab" /> 


<script language="javascript">

function quitBox(cmd) 
{      
    if (cmd=='quit')    
    {   
       window.opener.postMessage('location', '*');
       window.open(location, '_self').close();    
    }     
    return false;   
}

</script>

</body>
</html>


-2

Тільки якщо ви відкриєте нове вікно за допомогою window.open (), нове вікно зможе закрити за допомогою коду, як я вже згадував вище. Це прекрасно працює для мене :) Примітка: Ніколи не використовуйте href для відкриття сторінки в новій вкладці. Window.close () не працює з "href". Використовуйте замість window.open ().


1
Це просто заміна вікна потоку. Не більше.
RicardoGonzales

-3

Я хотів поділитися своїм "рішенням" з цим питанням. Схоже, більшість із нас намагаються закрити вікно браузера у звичайному сеансі браузера, коли користувач відвідує той чи інший веб-сайт, після того, як він відвідав інші веб-сайти, і перед тим, як відвідати ще деякі.

Однак моя ситуація полягає в тому, що я будую веб-додаток для пристрою, який, по суті, буде єдиним, що робить цей пристрій. Ви завантажите його, він запускає Chrome і переходить до нашого додатку. Він навіть не підключений до Інтернету, будь-які сервери, з якими він спілкується, є на наших локальних контейнерах Docker. Користувачеві потрібен спосіб закрити додаток (він же закриє Chrome), щоб він міг отримати доступ до терміналу для оновлення системи.

Тож він завантажиться, запустить Chrome у режимі кіоску за правильною адресою. Це може легко задовольнити другий варіант у специфікації:

Контекст перегляду доступний для скриптів, якщо це допоміжний контекст перегляду, створений сценарієм (на відміну від дії користувача), або якщо це контекст перегляду вищого рівня, історія сеансів містить лише один документ.

Тож просто дзвінок window.close()з мого додатку для кіоску просто працює !


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.