Jump to content

Great Rash

Expert
  • Posts

    7,974
  • Joined

  • Last visited

  • Days Won

    144

Everything posted by Great Rash

  1. Так, перезагрузил виртуальную машину, теперь у нее новый IP - 192.168.7.1 пингуется 192.168.1.27 пингуется 192.168.7.1
  2. нет не проще, я не совсем дурак и конечно использую его тоже, но он зараза под Дристой падает постоянно во-первых, и конкретно с определенным сайтом работать вообще не хочет если он локально ( ) во-вторых... оба не пингуются
  3. Выбираю Настройки -> Networking, вижу Adapter 1 (всего их четыре, но остальные неактивны): варианты в селекте: 1) Not connected 2) Local only 3) Имя моей сетевой карты (Realek RTL/8169... бла-бла-бла) - высталено 4) Контроллер Marvel Yukon 88E80... бла-бла-бла 5) Shared Networking (NAT) ipconfig на моей машине: ip - 192.168.1.27 шлюз - 192.168.1.1 ipconfig на виртуальной машине: ip - 192.168.131.66 шлюз - 192.168.131.254 P.S. Я и в Денвере дуб дубом, так что и про него рассказывайте если надо
  4. Слова "бридж" и "НАТ" мне ни о чем не говорят... Это тоже пустой набор фраз Я ж говорю, что я дуб дубом в этих делах... Если не сложно прошу объясните пошагово.
  5. Ссылочку пожалуйста Но по теме сказано ничего не было. Ставить пиратское ПО мне запрещено, так что эти варианты не предлагать. Так же не предлагать юзать VirtualBox, т.к. .vhd под ним не работают.
  6. Помогите решить проблему, понадобилась виртуальная машина с ИЕ6, нашел на сайте микрософта бесплатный образ XP SP3 с шестеркой. Устаноовил VirtualPC, но вот не могу получить доступ к локальным сайтам, которые запускаются из под Денвера. Я в сетевых подключениях, IP и всяких хостах - дерево... Объясните что надо сделать чтоб заработал http://localhost или http://mysite.local на виртуальной машине?
  7. Для небольшой промо-странички или блога в самый раз, никто не говорит о больших порталах.
  8. А все потому, что обнуление отступов вроде: * { margin: 0; padding: 0; } не всегда хорошо...
  9. Друзья, все уже есть, я ж говорю Hyphenator! http://code.google.com/p/hyphenator/
  10. Мне давно было интересно как устроен всеми любимый jQuery и вот я решил засесть за него (благо что исходники у него открытые). И вот, по просьбе камрада mishka2 я рассказываю, что я выяснил, как работает этот фреймворк и как написать свой такой же. Прежде всего пара фишек яваскрипта, про которые не все начинающие знают: 1) Имена функций: В яваскрипте валидными считаются любые имена функций, которые начинаются с буквы, со знака доллара ($) и со знака подчеркивания (_). Так что когда вы используете ваш любимый jQuery, вызывая к примеру $(document), знайте, что вы вызываете функцию у которой имя $ и передаете ей в качестве аргумента document. 2) Вызов функций: Обычно все пишут какую-нибудь функцию, к примеру: function myFunc() { alert(1); } // или так var myFunc = function() { alert(1); } а потом вызывают ее, но многие не знают, что в яваскрипте можно вызвать функцию сразу при создании вот таким методом: (function() { // создаем функцию alert(1); })(); // и тут же вызываем ее 3) Переменные и функции: Яваскрипт - это объектно ориентированный язык программирования. В нем все является либо объектами, либо свойствами объектов. Даже если вы используете процедурный подход к программированию (создаете отдельные функции и оперируете ими), вы все равно создаете объекты, т.к. в яваскипте любая функция - это объект. Т.е. вы можете вызвать ее через оператор new и рабоать с ней как с объектом. Когда вы создаете переменную в глобальной области видимости, то она записывается как свойство глобального объекта window. Т.е.var a = 1; и window.a = 1 эквивалентны. Ну вот теперь многие вещи в jQuery станут понятны. Самое интересное в jQuery то, что как только вы поздключили его на страницу он у вас сразу инициализирован. Давайте посмотрим как это сделано. 1) Для начала давайте создадим наш объект, назовем его Helper, у него будет пока единственный метод init(), который должен будет инициализировать его. А делать наш объект будет всего одну вещь - находить по ID элемент на странице или получать уже найденный элемент как ноду и возвращать его: var Helper = { init: function(elem) { elem = typeof elem == 'string' ? document.getElementById(elem) : elem; return elem; } } Фишка в том, что нам надо будет обязательно инициализировать наш объект, для того чтобы он заработал, т.е. нам нужно будет где-либо на странице вызвать метод init(): alert(Helper.init('id_элемента')); Но нам то нужно получить что-то вроде такого: alert(Helper('id_элемента')); Тут то нам и приходит на помощь вызов функции сразу при создании, единственное, что нам потребуется это анонимная функция (т.е. функция без имени), которая будет вызываться сразу же после создания и вспомогательная функция, которая будет инициализировать наш объект и возвращать его: (function() { // анонимная функция var Helper = function(elem) { // вспомогательная функция return new Helper.foo.init(elem); // которая возвращает нам уже проинициализированный объект } Helper.foo = { // наш основной объект init: function(elem) { // метод, где происходит инициализация elem = typeof elem == 'string' ? document.getElementById(elem) : elem; return elem; // метод возвращает нам ссылку на ноду } } })(); // сразу же вызываем анонимную функцию У внимательного читателя должен возникнуть вопрос: "Откуда взялся Helper.foo? И почему именно так?". Все дело в наследовании прототипов. Вообще, прототипы в яваскрипте это довольно сложная для понимания штука. В конце я дам ссылки на ресурсы где про это можно почитать. Признаюсь, сам перечитывал раз 10, но все равно не понял до конца как они работают. Скажу лишь, что когда мы пишем new Helper.foo.init(elem);, то не создаем новый объект с именем Helper.foo как вы могли подумать, а создаем новый объект с именем Helper.foo.init (т.к. init() - тоже функция), у которого нет ни одного метода. И чтобы использовать все методы которые мы будем добавлять в Helper.foo в дальнейшем на понадобится переопределить прототип Helper.foo.init. Пока все это звучит очень запутанно, но я надеюсь, что когда вы увидите дальнейший код, то все поймете. Итак, теперь у нас есть проинициализированный объект и казалось бы мы можем его начать вызывать, но (как вы должны знать) переменная Helper у нас получилась не глобальной, т.к. она находится внутри анонимной функции. Чтобы начать использовать наш Helper нам надо передать его в глобальную область видимости, вот так это сделано в jQuery: (function() { // анонимная функция var Helper = function(elem) { // вспомогательная функция return new Helper.foo.init(elem); // которая возвращает нам уже проинициализированный объект } Helper.foo = { // наш основной объект init: function(elem) { // метод, где происходит инициализация elem = typeof elem == 'string' ? document.getElementById(elem) : elem; return elem; // метод возвращает нам ссылку на ноду } } // передаем переменную Helper в глобальную область видимости window.Helper = Helper; })(); // сразу же вызываем анонимную функцию Все, теперь вы можете использовать проинициализированный объект: <body> <div id="test"></div> <script type="text/javascript"> alert(Helper('test')); </script> </body> Но позвольте, откуда же в jQuery берется доллар? Все очень просто - пусть у нас будет два доллара: (function() { var Helper = function(elem) { return new Helper.foo.init(elem); } Helper.foo = { init: function(elem) { elem = typeof elem == 'string' ? document.getElementById(elem) : elem; return elem; } } // создаем два доллара window.Helper = window.$$ = Helper; })(); И вызываем: <body> <div id="test"></div> <script type="text/javascript"> alert($$('test')); </script> </body> Однако, если в jQuery вызвать $('#test'), то он вернет не ссылку на ноду а сам себя, т.е. объект jQuery и чтобы получить ссылку на ноду в jQuery нам придется сделать что-то вроде этого: <body> <!-- Используем jQuery --> <div id="test"></div> <script type="text/javascript"> alert($('#test')); // выведет [object Object] (сам себя) alert($('#test')[0]); // выведет [object HTMLDivElement] </script> </body> Все это потому, что все найденные элементы jQuery цепляет к себе. Ничто не мешает нам сделать так же: (function() { var Helper = function(elem) { return new Helper.foo.init(elem); } Helper.foo = { init: function(elem) { elem = typeof elem == 'string' ? document.getElementById(elem) : elem; this[0] = elem // цепляем элемент к объекту return this; // возвращаем не элемент, а наш объект } } window.Helper = window.$$ = Helper; })(); Вот у нас и получится тоже самое: <body> <!-- Используем наш фреймворк --> <div id="test"></div> <script type="text/javascript"> alert($$('test')); // выведет [object Object] (сам себя) alert($$('test')[0]); // выведет [object HTMLDivElement] </script> </body> Теперь давайте добавим в наш фреймворк какой-нибудь метод, например пусть у него будет имя getNodeName(), а возвращать он будет имя ноды: (function() { var Helper = function(elem) { return new Helper.foo.init(elem); } Helper.foo = { init: function(elem) { elem = typeof elem == 'string' ? document.getElementById(elem) : elem; this[0] = elem return this; }, getNodeName: function() { // наш новый метод // возвращает имя ноды найденного объекта в верхнем регистре return this[0].nodeName.toUpperCase(); } } window.Helper = window.$$ = Helper; })(); Давайте попробуем при помощи нашего нового метода узнать имя ноды: <body> <div id="test"></div> <script type="text/javascript"> alert($$('test').getNodeName()); // Ошибка !!! </script> </body> Почему же это не работает? Как я уже говорил выше, вспомогательная функция Helper создает новый объект с именем Helper.foo.init, а внутри нашего метода init() нет никаких других методов. Поэтому нам надо переопределить прототип для Helper.foo.init, т.е. указать скрипту явно, что шаблоном нашего объекта является не Helper.foo.init, а Helper.foo. Причем наш объект foo должен храниться обязательно как свойство объекта Helper иначе (если я правильно понял, прочитав кучу статей про прототипы) переопределить прототип не получится. (function() { var Helper = function(elem) { return new Helper.foo.init(elem); } Helper.foo = { init: function(elem) { elem = typeof elem == 'string' ? document.getElementById(elem) : elem; this[0] = elem return this; }, getNodeName: function() { return this[0].nodeName.toUpperCase(); } } Helper.foo.init.prototype = Helper.foo; window.Helper = window.$$ = Helper; })(); Вот теперь все заработает: <body> <div id="test"></div> <script type="text/javascript"> alert($$('test').getNodeName()); // выведет DIV </script> </body> Ну вот и все, теперь вы можете расширять свой фреймворк, добавляя туда новые методы и использовать его так же как и jQuery. Теперь вы представляете как устроен этот фреймворк. Конечно то что я тут описал - это очень сильно упрощенная версия jQuery. Она умеет находить ноду только по ID и в ней нет кучи полезных фишек jQuery. Но я не волшебник, я только учусь. Многое еще остается в jQuery для меня не ясным, но надеюсь со временем я его таки доковыряю P.S. Что я читал: http://javascript.ru/ecma/part8#_Prototype_ http://javascript.ru/tutorial/object/inher...type-i-prototip http://code.jquery.com/jquery-1.4.2.js http://dklab.ru/chicken/nablas/40.html
  11. Создаем GUI Итак, давайте приступим к созданию нашего интерфеса. Все стили для него я уже привел, так что ничто не будет отвлекать нас от чистого яваскрипта, ура! Метод, который будет строить наш интерфейс мы назовем generateGUI (многие уже и так об этом догадалиь, внимательно посмотрев предыдущую часть урока). Для создания элементов на странице можно воспользоваться тремя способами: 1) использовать метод write или writeln 2) использовать метод innerHTML 3) использовать связку createElement и appendChild Первый метод пишет что-либо в документ в том месте в котором вызван, различие между write и writeln в том, что writeln добавляет в конце перенос строки (типа \r\n - возврат каретки и новая строка). Второй метод записывает HTML в выбранную ноду. Третий метод (он типа самый правильный) работает с DOM (объектной моделью документа) и использует ее методы для создания элемента (document.createElement('имя_тега')) и втравки созданного элемента на страницу в выбранную ноду (element.appendChild(newElement)). Я создавал своего сапёра с таким расчетом, чтобы его можно было вставить в любое место на сайте (типа как виджет, чтобы пользователей развлекать). Поэтому я решил соединить первый и третий методы создания объектов на странице. А именно, мы сначала создадим контейнер при помощи document.writeln('html'), а потом в него понапихаем все задуманные элементы интерфейса. Итак, приступим к написанию кода. Для создания основного контейнера я выделил специальный метод у нашего объекта MyMineSweeper и назвал его writeMainContainer: var MyMineSweeper = { // наш главный метод, он будет инициализировать нашего сапёра init: function(o) { this.W = o ? o.W : 7; this.H = o ? o.H : 7; this.bombs = o ? o.bombs : Math.floor(this.W * this.H / 4); this.placedBombs = this.bombs; this.generateGUI(); }, generateGUI: function() { /* * интерфейс будет создаваться только один раз, * поэтому, чтобы не появилось дубликатов, проверяем * не создан ли уже наш контейнер */ if (!this.game) { // если такой переменной еще нет this.game = this.writeMainContainer(); // то создаем наш контейнер } }, // метод который пишет в документ код нашего контейнера writeMainContainer: function() { // это, собственно, html-текст, который будет вписан в документ var html = '<div id="game" class="game"></div>'; // вписываем его в документ document.writeln(html); /* * а потом, находим наш контейтнер по ID и возвращаем его, * чтобы получить ссылку на ноду * и работать уже с полученным объектом */ return document.getElementById('game'); } } Теперь мы можем создавать нашего сапера в любом месте страницы, вписав в нужном месте вот такой код: <!-- допустим создаем сапёра в <body> --> <body> <script type="text/javascript"> MyMineSweeper.init(); </script> </body> Причем если вы вызовете метод init() два раза (или больше), нового контейнера создано не будет. Теперь надо немного остановиться на одном из элементов DOM, который немного не похож на другие - я имею в виду таблицу (<table>). Все дело в том как в таблицах создаются и находятся строки и столбцы. Дело в том, что таблица сама по себе является двумерным массивом (т.е. массивом, каждый элемент которого тоже массив). Вы конечно можете создавать строки и ячейки в таблице при помощи createElement, но гораздо правильней использовать для этого специальные методы: 1) метод table.insertRow(index) - создает новую строку (<tr>) и возвращает ссылку на нее, где index - это номер создаваемой строки (начиная с нуля, как в обычном массиве). Пример: // создаем таблицу var table = document.createElement('table'); // создаем строку var row = table.insertRow(0); alert(row); // создаем еще одну строку, // которая будет вставлена под первой var row2 = table.insertRow(1); // если строка будет с меньшим или с одинаковым индексом, // то она будет вставлена над уже созданной строкой var row3 = table.insertRow(0); // эта строка будет выше всех 2) метод row.insertCell(index) - создает новую ячейку в уже созданной строке и возвращает ссылку на нее, где index - это номер создаваемой ячейки (начиная с нуля) Пример: // создаем таблицу var table = document.createElement('table'); // создаем строку var row = table.insertRow(0); alert(row); // создаем ячейку var cell = row.insertCell(0); alert(cell); // аналогично строкам, если задать меньший или одинаковый индекс // ячейка будет вставлена впереди var cell2 = row.insertCell(0); // эта ячейка будет первой Находить строки и ячейки можно при помощи методов rows() и cells() объекта таблицы. Эти методы содержат массивы строк и ячеек соответственно. Таким образом, создавая таблицу, мы сразу имеем двумерный массив, с которым удобно работать, обходя его, напрмер, при помощи цикла for. Ну вот, вроде про таблицы рассказал. Теперь можно наполнять наш контейнер элементами интерфейса (я не буду подробно описывать создание элементов, тут нет ничего сложного): var MyMineSweeper = { // наш главный метод, он будет инициализировать нашего сапёра init: function(o) { this.W = o ? o.W : 7; this.H = o ? o.H : 7; this.bombs = o ? o.bombs : Math.floor(this.W * this.H / 4); this.placedBombs = this.bombs; this.generateGUI(); }, generateGUI: function() { // интерфейс будет создаваться только один раз if (!this.game) { this.game = this.writeMainContainer(); // создаем основную таблицу, состоящую из двух строк (первая - статистика, вторая - игровое поле и инпуты) this.gameCont = document.createElement('table'); this.gameCont.className = 'game-cont'; // присваиваем нужное имя css-класса // эти строки нам как объекты не нужны, поэтому переменных не создаем this.gameCont.insertRow(0); // создаем первую строку this.gameCont.insertRow(1); // и вторую строку // создаем ячейку для инпутов (игровое меню) this.gameMenu = this.gameCont.rows[0].insertCell(0); this.gameMenu.rowSpan = 2; // оно будет занимать 2 строки this.gameMenu.className = 'game-menu'; // назначаем класс this.gameMenu.appendChild(document.createTextNode('Ширина поля:')); // втавляем текстовую ноду this.gameMenu.appendChild(document.createElement('br')); // и перенос строки (<br />) // создаем инпут для ввода ширины доски this.WInput = document.createElement('input'); this.WInput.type = 'text'; // назначаем тип инпута - текст this.gameMenu.appendChild(this.WInput); // вставляем созданный инпут this.gameMenu.appendChild(document.createTextNode('Высота поля:')); // вставляем текстовую ноду this.gameMenu.appendChild(document.createElement('br')); // вставляем перенос // все тоже самое для инпуда, предназначенного для ввода высоты доски this.HInput = document.createElement('input'); this.HInput.type = 'text'; // назначаем тип инпута - текст this.gameMenu.appendChild(this.HInput); this.gameMenu.appendChild(document.createTextNode('Кол-во мин:')); this.gameMenu.appendChild(document.createElement('br')); // создаем инпут для ввода количества бомб this.BInput = document.createElement('input'); this.BInput.type = 'text'; // назначаем тип инпута - текст // создаем кнопку запуска игры this.Init = document.createElement('input'); this.Init.type = 'button'; // назначаем тип инпута - кнопка this.Init.value = 'Старт'; // надпись на кнопке this.Init.className = 'game-start-button'; // назначаем класс // вставляем инпут и кнопку this.gameMenu.appendChild(this.BInput); this.gameMenu.appendChild(this.Init); // создаем ячейку статистики this.gameStats = this.gameCont.rows[0].insertCell(1); // создаем ячейку для игрового поля this.gameField = this.gameCont.rows[1].insertCell(0); this.gameField.className = 'game-field'; // назначаем класс // наконец, вставляем наш основной контейнер внутрь основного this.game.appendChild(this.gameCont); } // если играем второй раз, то старую доску надо заменить на новую if (this.board) { // если доска уже существует this.board.parentNode.removeChild(this.board); // удаляем ее из дерева нод this.board = null; // и очищаем переменную } /* * игровую доску будем генерировать кажный раз заново * поэтому создаем ее вне условия * метод generateField() будет генерить доску (расставлять бомбы, вписывать цифры вокруг бомб и т.п.), * а потом вернет созданную таблицу */ this.board = this.generateField(); this.board.cellSpacing = 0; // убираем отступы между ячейками (нельзя задать в CSS кроссбраузерно) this.board.className = 'game-board'; // назначаем класс // вставляем доску в ячейку this.gameField.appendChild(this.board); // записываем в поле статистики размер созданной доски и количество бомб на поле this.gameStats.innerHTML = 'Новая игра: поле ' + this.W + 'x' + this.H + ', ' + this.bombs + 'мин'; // в этом методе будут назначаться обработчики событий интерфейса this.setupEvents(); }, writeMainContainer: function() { var html = '<div id="game" class="game"></div>'; document.writeln(html); return document.getElementById('game'); } } Ну вот мы и сгенерировали наш интерфейс, если вы закомментируете кусок кода где используются еще не созданные методы generateField() и setupEvents(), а потом запустите скрипт, то увидете всю красоту. На данном этапе можете поэкспериментировать со своим интерфейсом, если есть желание поменяйте стили или вообще измените структуру интерфейса, это ни на что не повлияет в дальнейшем. Главное не меняйте имена переменных. Ну а мне пока разрешите откланяться. Впереди нас ожидает самое интересное - генерация игровой доски, назначение обработчиков событий, много циклов, логики и т.п. Продолжение будет как только выпадет свободная минутка. Критику, советы, прочее и прочее шлите в приват.
  12. А разве нельзя на одной точке карты расположить два маркера и у каждого задать иконку, иконка первого маркера будет подложкой, а иконка второго - фоткой. Почитал API - вроде там можно z-index регулировать...
  13. Уже есть несколько инструментов для более-менее адекватной расстановки элементов, написанные на JavaScript. Например Hyphenator. С ним justify-тексты смотрятся довольно неплохо... Хотя наверное вы все же правы...
  14. Вообще я очень давно мечтал написать самостоятельно игрушку. Но, как это часто бывает, у меня не хватало знаний и идей для реализации задуманного. Долго я пытался найти хоть аккие-нибудь уроки по данной теме в сети, но попадались либо статьи на общие темы, не представляющие для меня интереса, либо очень сложные в понимании статьи по программированию какого-нибудь ИИ и т.п. В общем никакого сочувствия к нубам среди маститых девелоперов игр я не встретил, не говоря уже о том, что в рунете ситуация с написанием уроков вообще и уроков по нужной мне теме в частности удручающая (все либо тырят статьи друг у друга, либо переводят забугорные). Ну да ладно, оставим лирику. Одно время я любил играть в Сапера (Mine Sweeper), я думаю все, кто хоть немного знаком с компьютерами, знают эту логическую игру. Вот я и подумал, а не написать ли мне своего сапера! Эта игра показалась мне достаточно простой для реализации, ведь там нет никакой супер физики, нет искуственного интеллекта и прочих сложных для новичка вещей. Сказано - сделано! Итак, я представляю вашему вниманию урок по написанию вашей первой игры, встречайте - Сапёр! (бурные овации, крики "браво!") Хватит слов, приступаем... Базовая верстка Собственно базовой верстки как таковой у нас не будет, так как весь HTML мы будем генерить яваскриптом. Но нам потребуется базовый макет страницы и стили для генерируемого контента. Вот так будет выглядеть наша страничка: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ru"> <head> <title>Мой Сапёр</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <style type="text/css"> * { margin: 0; padding: 0; } html, body { font-family: "Trebuchet MS", Veradna, Tahoma, Arial, sans-serif; font-size: 11px; } .game { padding: 5px; } .game-cont { border: 0; } .game-cont td { padding: 5px; vertical-align: top; border: #9cb0ca 3px outset; background: #bfd3ed; } .game-menu { width: 150px; } .game-menu input { width: 144px; border: #9cb0ca 3px inset; } input.game-start-button { width: 150px; height: 26px; margin-top: 1.5em; border: #9cb0ca 3px outset; background: #bfd3ed; } .game-stats { text-align: center; } .game-board { border: 0; border-spacing: 0; border-collapse: collapse; } .game-board td { width: 20px; height: 20px; line-height: 20px; text-align: center; border: #9cb0ca 1px solid; } </style> <script type="text/javascript"> // тут будем писать скрипт </script> </head> <body> </body> </html> Плюс для работы нашего сапера нам потребуется навешивать события. Для этого можно использовать связку element.addEventListener() и element.attachEvent(), но у них есть свои проблемы. По этому я погуглил и нашел неплохой урок по созданию библиотеки для работы с добавлением и удалением обработчиков событий. Почитать этот, несомненно, полезный и нужный урок вы можете тут. Настоятельно рекомендую всем ознакомиться. Так же там в конце статьи есть ссылка на скачивание библиотеки event.js. В данной библиотеке решено большинство проблем, связанных с кроссбраузерной обработкой событий, поэтому в нашем проекте мы будем использовать ее. Подключаем библиотеку в наш проект: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ru"> <head> <title>Мой Сапёр</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <style type="text/css"> * { margin: 0; padding: 0; } html, body { font-family: "Trebuchet MS", Veradna, Tahoma, Arial, sans-serif; font-size: 11px; } .game { padding: 5px; } .game-cont { border: 0; } .game-cont td { padding: 5px; vertical-align: top; border: #9cb0ca 3px outset; background: #bfd3ed; } .game-menu { width: 150px; } .game-menu input { width: 144px; border: #9cb0ca 3px inset; } input.game-start-button { width: 150px; height: 26px; margin-top: 1.5em; border: #9cb0ca 3px outset; background: #bfd3ed; } .game-stats { text-align: center; } .game-board { border: 0; border-spacing: 0; border-collapse: collapse; } .game-board td { width: 20px; height: 20px; line-height: 20px; text-align: center; border: #9cb0ca 1px solid; } </style> <!-- Подключаем event.js --> <script src="event.js" type="text/javascript"></script> <!-- А тут уже будет наш код --> <script type="text/javascript"> // тут будем писать скрипт </script> </head> <body> </body> </html> Использовать эту библиотеку очень просто, чтобы добавить обработчик для какого либо события нужно вызвать метод add(), а чтобы удалить событие - remove(): // к примеру добавим алерт на клик var clickHandler = function() { alert('ok!'); } // вызываем метод add() объекта Event // первый параметр - елемент к которому цепляем обработчик // второй параметр - событие на которое будет срабатывать функция (без префикса "on"! не забывайте) // третий параметр - функция-обработчик события Event.add(element, 'click', clickHandler); // то же самое для remove() Event.remove(element, 'click', clickHandler); Просто правда? Ну все, вроде с приготовлениями закончили, теперь можно приступать к написанию нашего сапёра. Поехали! Проектирование А не было у меня никакого проектирования. Я просто тупо сел однажды и написал, все придумывая на ходу... Но многие умные дяди поголовно рекомендуют начинать с проектирования и называют такие умные слова и аббревиатуры как UML и блок-схемы. Наверное эти умные дяди не зря все это делать рекомендуют, так что и вы начните лучше с проектирования... Ну-с продолжим... Создаем объект Для тех кто не знаком с ООП в яваскрипте рекомендую заглянуть в эту тему, там я описывал основные принципы объектно-ориентированного программирования в JavaScript и приводил ссылки на ресурсы где можно почитать об этом более подробно. Для тех кто уже дружит с объектами в JavaScript приступим к созданию нашего объекта (HTML-код я опускаю, больше он меняться не будет, далее будет идти только яваскрипт): var MyMineSweeper = { // наш главный метод, он будет инициализировать нашего сапёра init: function(o) { this.W = o ? o.W : 7; this.H = o ? o.H : 7; this.bombs = o ? o.bombs : Math.floor(this.W * this.H / 4); this.placedBombs = this.bombs; this.generateGUI(); } } Итак, что тут происходит: Мы создаем главный метод - init(), который будет запускать нашего сапера в первый раз, а так же когда юзер захочет переиграть заново. В качестве параметра этот метод будет принимать объектный литерал (или объект в формате JSON - JavaScript Object Notation), в котором будут задаваться необходимые параметры для построения игрового поля (далее я буду назвать игровое поле просто доской, для краткости). Вот какие данные мы описываем в методе init(): 1) this.W - ширина доски (от слова width), по умолчанию будет равна 7 (формат ширины у нас будет задаваться не в каких-либо единицах измерения, а в клетках - 7 означает, что ширина доски будет 7 клеток) 2) this.H - высота доски (от слова height), по умолчанию тоже 7 клеток 3) this.bombs - количество бомб на доске, если не задано иное будет заполнена 1/4 доски (я не знаю сколько бомб на доске в настоящем сапёре, поэтому поставил так чтобы черверть доски была заполнена бомбами) 4) this.placedBombs - сколько бомб уже установлено (это число будет уменьшаться по мере того как программа будет расставлять мины на карте) 5) this.generateGUI() - этот метод будет генерить GUI (Graphical User Interface - по русски все что юзер будет видеть на экране, т.е. наш HTML) Я не хочу создавать клон виндового сапёра, поэтому я решил, что не стоит ограничивать пользователя всего тремя досками (маленькая, большая и средняя), в нашем мега-сапёре юзер сам решит сколько на сколько будет у него доска и сколько на ней будет бомб, для сего мы предусмотрим три поля ввода. Метод init() будет устанавливать все данные по умолчанию, но если мы передадим ему как параметр объектный литерал (я его обозвал o - коротко и ясно, но вообще такие короткие названия переменным давать не стоит ибо потом запутаться где что можно), то наш сапёр примет те параметры которые пользователь ввел в поля ввода. Сам GUI мы будем строить на таблицах. "Почему не на дивах?", - спросят некоторые сильно продвинутые верстальщики. А все потому, что нам пофиг на семантику и т.п., а таблицы гибче, требуют меньше усилий на верстку и не развалятся в нашем обожаемом ИЕ. Но если вы хотите, то стройте на дивах, может оно и красивше выйдет. Итак наш GUI будет содержать: 1) поле ввода для задания ширины доски (в клетках) 2) поле ввода для задания высоты доски (в клетках) 3) поле ввода для задания количества бомб на доске 4) кнопку с надписью "Старт!", по нажатию на которую будет перезапускаться игра 5) область статистики (туда мы будем писать Game Over уже или еще нет) 6) собственно саму доску, на которой юзер будет искать мины На этом пока позвольте откланяться, строить наш GUI будем в следующий раз. И так уже многа букав написал. Продолжение будет. Критику, советы, предложения, вопросы, хвальбы, лесть и т.п. прошу писать в личку. P.S. Вот что у нас получится в итоге: http://mine-sweeper.narod.ru/
  15. 2Verder: Сайт вашего любимого эппла, кстати, фиксированный
  16. Простите конечно, но это просто капец...
  17. В инете важна инфа, а не дизайн Так что в пень дизайнеров, даешь возврат в девяностые! Красотень нужна только промо сайтам, а для них и фикс сойдет - один хрен из полиграфии пришли. А данный шаблон переделать в резину не составит труда, в чем прикол не догнал.
  18. Учите, это просто. «frameset» на htmlbоok.ru «frame» на htmlbоok.ru «верстка фреймами» в Google. При желании (если не будете пить пиво и гулять, а будете учить) освоите за день (ну максимум 2 дня). Если будет что-то не понятно спрашивайте тут. А вот чтобы так тупо за вас сделали не дождетесь. Своей головой думать надо.
  19. «firebug lite» в Google. вдруг еще надо...
  20. сто раз обсуждали ну вот к примеру один неплохой способ
  21. Да, мой косяк... вот правильная функция: // с флагом function switchVisibility(obj) { obj = typeof obj == 'string' ? document.getElementById(obj) : obj; if (!obj.flag) { obj.flag = true; obj.style.display = 'block'; } else { obj.flag = false; obj.style.display = 'none'; } }
  22. Весь код в студию.
  23. Поставить нормальный line-height и текст уже не будет восприниматься как коробка. Так что с этим утверждением не согласен. Так же не согласен с утверждением, что глазу не за что зацепиться, при чтении книги он же за что-то цепляется! Единственное, в вебе надо текст чаще на абзацы разбивать. Длинный текст без абзацев - очень фигово читается.
  24. Теперь все понятно! Еще раз спасибо.
  25. Я тут почитывал форум и наткнулся на такие выражения: Объясните мне чем плохо выравнивать текст по ширине? В книгах же выравнено и ничего. Все выравнивают текст в дипломах, курсовых, рефератах по ширине и ничего. Многие не любят такое выравнивание из-за "дыр" в тексте, так их поправить можно...
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy