Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/28/2013 in Posts

  1. Всем доброго времени суток. Задача: необходимо сделать чтобы при наведении на ссылку в виде картинки (обрамленную обводкой) сбоку от нее расширялось место (увеличивается ширина обрамленной области) и там появлялась текстовая подсказка. .block a { float:left; transition: all 0.4s linear; -moz-transition: all 0.4s linear; -webkit-transition: all 0.4s linear; -o-transition: all 0.4s linear; width:30px; height:30px; border:1px solid #CECECE; background: #fff url(images/block.png) no-repeat; } .block a:after { content:'подсказка'; float:left; margin-left:30px; font-size:22px; line-height:34px; color:transparent; } .block a:hover { width:50px; background: url(images/block_hover.png) no-repeat; } .block a:hover:after { font-size:22px; color:red; } Как видите я пробую реализовать задачу через псевдокласс :after, но проблема в том, что подсказка появляется моментально, без анимации и при этом плавно расширяющийся блок краем плавно едет по подсказке, то есть имеет место такой визуальный "глюк": Помогите либо исправить ошибку в коде, либо найти другое решение. Спасибо заранее.
    1 point
  2. + ещё overflow:hidden; для span добавить.
    1 point
  3. Транзишены для псевдоэлементов работают, вроде, только в ФФ. Использую обычные теги, либо может подойдет такая реализация - http://jsfiddle.net/KDfav/
    1 point
  4. Всё вроде как(на первый взгляд) неплохо. Но! браузер IE отказывается у меня отображать шрифт velesbold! (как на холсте так и в теге заголовка..) http://webmaster.ayr...sbold_error.jpg Что-то мн еподсказывает что сам код тут не причем. Нужно копать в сторону CSS файла подключения . гугл то отдает шрифт нормально и контент тайп у него font/eot а вот второй сервис отдает шрифт в формате eot как обычный octet-stream может в этом и дело. фик знает Попробуйте сгенерит ькакойнить шрифт через сервис http://www.fontsquirrel.com/tools/webfont-generator И использовать его на своем сайте, не подгружат ькороче шрифты со сторонних сервисов.
    1 point
  5. ресайзить лучше на стороне сервера ибо нафига загружать огромные изображения чтоб потом их уменьшать?
    1 point
  6. Ну вот вам пример как работает webfontloader http://fiddle.jshell.net/F47E2/5/
    1 point
  7. Есть библиотека для подгрузки шрифтов https://developers.g.../webfont_loader Кроме шрифтов с гуглошрифтов, можно указывать и свои адреса хранилищ. Плюс там и события есть судя по API Может поможет. Еще вот плагин для jQuery нашелся http://code.google.com/p/jquery-fontavailable/ который проверяет поддерживает ли браузер указанный шрифт, теоритически если поддерживает то шрифт уже должен быть загружен и готов для использования. Ну это тестить нужно.
    1 point
  8. Google ??? О_О не, не слышал)))) кстати я год работал (учился) только благодаря Google... результатов вагон) сайтов 20 сделал... 15 из них продал))) так что пользуйтесь гуглом) а на форум бежать только после него)
    1 point
  9. http://www.cssplay.c...le-3column.html http://fiddle.jshell.../19/show/light/ http://chikuyonok.ru/playground/cols/ http://matthewjamest...er-css-no-hacks http://vitaly.hariso...ent-blocks.html http://gruzzilkin.110mb.com/layout/ http://chikuyonok.ru.../float-columns/ http://tsvensen.gith...om/equalize.js/ http://www.jainaewen...ht-columns.html http://peterned.home...csslayout1.html изучайте
    1 point
  10. Формула движения Так как мы будем делать движение не просто увеличивая координату, а движение с ускорением и замедлением, то нам понадобится некая формула движения. Я не математик, более того, с математикой я совсем не дружу, так что формулу расчета движения я искал очень долго и упорно гугля. И совершенно случайно наткнулся на один пост в форуме где эта формула приведена: x = начальная_координата + (конечная_координата - начальная_координата) * коэфицент; //где коэфицент = время_прошедшее_с_начала_анимации / время_за_которое_анимация_должна_закончиться; Время за которое анимация должна закончиться - это и есть наш параметр this.duration, который, как мы решили, по умолчанию равен 500 миллисекунд или 0,5 секунды. Единственное чего нет в нашем аниматоре, чтобы реализовать эту формулу движения - это свойства, в котором бы хранилось время, прошедшее с начала анимации. Чтобы узнать сколько времени прошло с начала анимации нам надо запомнить какое было время в момент клика по кнопке, для этого мы создадим новое свойство нашего объекта и назовем его, скажем startTime: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); // запоминаем время начала анимации, в миллисекундах this.move(); }, move: function() { if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { // производим расчет движения if (true) { window.clearInterval(self.obj.interval); } }, 10); } } Чтобы узнать сколько времени прошло с начала анимации нам надо внутри интервала вычитать из текущего времени время которое мы запомнили ранее: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); // запоминаем время начала анимации, в миллисекундах this.move(); }, move: function() { if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - this.startTime; // вычитаем из текущего времени время начала анимации if (true) { window.clearInterval(self.obj.interval); } }, 10); } } Тут мы сталкиваемся с одной проблемой. Дело в том что внутри нашей анонимной функции не будет переменной this.startTime, все это из-за того, что ключевое слово this в данном случае будет ссылаться не на наш объект Animate, а на объект window. Это прекрасно видно если запустить alert: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { alert(this); // проверяем куда ссылается this if (true) { window.clearInterval(self.obj.interval); } }, 10); } } Animate.init({obj: 'test', from: 0, to: 0}); // выдаст [object DOMWindow] или что-то вроде того Чтобы решить эту проблему нужно просто запомнить в переменной ссылку на наш объект, а потом обращаться к свойствам и методам нашего объекта через эту переменную: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; // запоминаем ссылку на наш объект (принято называть эту переменную self или parent) if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; // вот теперь все будет работать правильно if (true) { window.clearInterval(self.obj.interval); } }, 10); } } Теперь все готово для того чтобы реализовать движение нашего блока по формуле которую я привел выше: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; // запоминаем ссылку на наш объект if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; // высчитываем время, прошедшее с начала анимации var k = elapsedTime / self.duration; // высчитываем коэффициент, отношение прошедшего времени анимации ко времени анимации (изменяется от 0 до 1) var result = self.from + (self.to - self.from) * k; if (true) { window.clearInterval(self.obj.interval); } }, 10); } } Чтобы остановить анимацию в нужный момент (т.е. через 500 миллисекунд по умолчанию) нам надо проверить прошло ли уже пол секунды, т.е. равно ли отношение elapsedTime / self.duration единице (500 / 500 = 1), а для надежности лучше проверить не больше ли оно единицы: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; // запоминаем ссылку на наш объект if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; // высчитываем время, прошедшее с начала анимации var k = elapsedTime / self.duration; // высчитываем коэффициент, отношение прошедшего времени анимации ко времени анимации (изменяется от 0 до 1) var result = self.from + (self.to - self.from) * k; self.obj.style.cssText = self.attr + ': ' + result + self.units; // применяем полученный результат к анимируемому объекту if (k >= 1) { // если анимация дошла до конца, очищаем интервал, тем самым останавливая анимацию window.clearInterval(self.obj.interval); } }, 10); } } Как вы помните параметр this.attr у нас по умолчанию равен left, а параметр this.units - по умолчанию равен px, соответственно в результате у нас получится такая строка: self.obj.style.cssText = 'left: ' + result + 'px'; Теперь откройте html-файл с базовой версткой и на кнопки влево и вправо на событие onclick повесте вызов нашего аниматора: <div class="wrap"> <div class="left"> <!-- Двигаем справа налево --> <input class="button" type="button" value="←" onclick="Animate.init({obj: 'test', from: 450, to: 0});" /> </div> <div class="right"> <!-- Двигаем слева направо --> <input class="button" type="button" value="→" onclick="Animate.init({obj: 'test', from: 0, to: 450});" /> </div> <div class="container"> <div id="test" class="item"></div> </div> </div> После этого откройте html-файл в вашем любимом браузере и понажимайте стрелки влево и вправо. Вы увидите, что красный блок будет ездить туда-сюда. Один проход блока будет занимать 0,5 секунды. Вы можете попробовать изменить скорость анимации, изменив параметр duration на необходимое значение: <!-- Двигаем медленнее --> <div class="wrap"> <div class="left"> <!-- Двигаем справа налево медленнее --> <input class="button" type="button" value="←" onclick="Animate.init({obj: 'test', from: 450, to: 0, duration: 1000});" /> </div> <div class="right"> <!-- Двигаем слева направо медленнее --> <input class="button" type="button" value="→" onclick="Animate.init({obj: 'test', from: 0, to: 450, duration: 1000});" /> </div> <div class="container"> <div id="test" class="item"></div> </div> </div> <!-- Или двигаем быстрее --> <div class="wrap"> <div class="left"> <!-- Двигаем справа налево медленнее --> <input class="button" type="button" value="←" onclick="Animate.init({obj: 'test2', from: 450, to: 0, duration: 250});" /> </div> <div class="right"> <!-- Двигаем слева направо медленнее --> <input class="button" type="button" value="→" onclick="Animate.init({obj: 'test2', from: 0, to: 450, duration: 250});" /> </div> <div class="container"> <div id="test2" class="item"></div> </div> </div> Отлично, все работает. Теперь осталось дело за малым - заставить наш блок двигаться с ускорением и замедлением. В нашей формуле var result = self.from + (self.to - self.from) * k; коэффициент - это как бы скорость красного блока в определенный момент времени. Чтобы получить движение с ускорением нам нужно чтобы с течением времени скорость становилась больше и больше, для этого будем возводить скорость (т.е. коэффициент k) в квадрат. Чтобы нам было удобней работать с изменениями коэффициента давайте создадим в нашем объекте еще один метод, который назовем например calculate, этот метод будет возвращать скорость возведенную в квадрат: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; var k = elapsedTime / self.duration; var result = self.from + (self.to - self.from) * self.calculate(k); self.obj.style.cssText = self.attr + ': ' + result + self.units; if (k >= 1) { window.clearInterval(self.obj.interval); } }, 10); }, calculate: function(k) { // создаем новый метод return Math.pow(k, 2); // который возвращает коэффициент, возведенный в квадрат } } Давайте теперь снова запустим наш html-файл и посмотрим как ведет себя красный блок. Вы увидите что теперь он ездит туда-сюда с ускорением. Но теперь появилась еще одна небольшая проблема - дело в том, что наш коэффициент k изменяется от 0 до 1, а значит он является дробным числом, из-за этого (если несколько раз понажимать на стрелки) блок иногда немного переезжает за границу голубого блока или недоезжает до нее. Для того чтобы исправить это поведение давайте создадим еще один метод который будет исправлять неверные значения: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; var k = elapsedTime / self.duration; var result = self.from + (self.to - self.from) * self.calculate(k); result = self.fixResult(result); // исправляем неверное значение результата self.obj.style.cssText = self.attr + ': ' + result + self.units; if (k >= 1) { window.clearInterval(self.obj.interval); } }, 10); }, calculate: function(k) { return Math.pow(k, 2); }, fixResult: function(num) { // новый метод который будет исправлять результат num = Math.round(num); if (this.from < this.to) { // если блок едет слева направо if (num > this.to) { num = this.to; } if (num < this.from) { num = this.from; } } else { // если блок едет справа налево if (num < this.to) { num = this.to; } if (num > this.from) { num = this.from; } } return num; } } После всех дополнений, наш красный блок будет ездить как положено, а именно, строго в пределаз голубого блока. Давайте теперь реализуем движение с замедлением. Для начала давайте создадим еще один параметр у нашего аниматора. При помощи этого параметра мы будем переключать режим в котором будет ездить наш блок (с ускорением или с замедлением). Допустим параметр будет называться type и по умолчанию будет иметь значение accel (от английского acceleration): var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.type = params.type ? params.type : 'accel'; // новый параметр, по умолчанию равен ускорению - 'accel' this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; var k = elapsedTime / self.duration; var result = self.from + (self.to - self.from) * self.calculate(k); result = self.fixResult(result); self.obj.style.cssText = self.attr + ': ' + result + self.units; if (k >= 1) { window.clearInterval(self.obj.interval); } }, 10); }, calculate: function(k) { if (this.type == 'accel') { // если задано движение с ускорением return Math.pow(k, 2); // возвращаем коэффициент в квадрате } else { // если вдруг у нас задано иное невалидное значение this.type (например vasya_pupkin) return k; // тогда просто возвращаем коэффициент и блок поедет без ускорения } }, fixResult: function(num) { num = Math.round(num); if (this.from < this.to) { if (num > this.to) { num = this.to; } if (num < this.from) { num = this.from; } } else { if (num < this.to) { num = this.to; } if (num > this.from) { num = this.from; } } return num; } } Чтобы реализовать замедление, нам надо совершать действие обратное ускорению, т.е. действие обратное возведению в степень, а именно извлечение квадратного корня. Параметр, который будет отвечать за замедление давайте назовем decel (от английского deceleration): var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.type = params.type ? params.type : 'accel'; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; var k = elapsedTime / self.duration; var result = self.from + (self.to - self.from) * self.calculate(k); result = self.fixResult(result); self.obj.style.cssText = self.attr + ': ' + result + self.units; if (k >= 1) { window.clearInterval(self.obj.interval); } }, 10); }, calculate: function(k) { if (this.type == 'accel') { // если задано движение с ускорением return Math.pow(k, 2); // возвращаем коэффициент в квадрате } else if (this.type == 'decel') { // если задано движение с замедлением return Math.sqrt(k); // возвращаем квадратный корень из коэффициента } else { // если вдруг у нас задано невалидное значение this.type return k; // тогда просто возвращаем коэффициент } }, fixResult: function(num) { num = Math.round(num); if (this.from < this.to) { if (num > this.to) { num = this.to; } if (num < this.from) { num = this.from; } } else { if (num < this.to) { num = this.to; } if (num > this.from) { num = this.from; } } return num; } } Давайте попробуем все в действии: <!-- Двигаемся с ускорением --> <div class="wrap"> <div class="left"> <input class="button" type="button" value="←" onclick="Animate.init({obj: 'test', from: 450, to: 0, type: 'accel'});" /> </div> <div class="right"> <input class="button" type="button" value="→" onclick="Animate.init({obj: 'test', from: 0, to: 450, type: 'accel'});" /> </div> <div class="container"> <div id="test" class="item"></div> </div> </div> <!-- Двигаемся с замедлением --> <div class="wrap"> <div class="left"> <input class="button" type="button" value="←" onclick="Animate.init({obj: 'test2', from: 450, to: 0, type: 'decel'});" /> </div> <div class="right"> <input class="button" type="button" value="→" onclick="Animate.init({obj: 'test2', from: 0, to: 450, type: 'decel'});" /> </div> <div class="container"> <div id="test2" class="item"></div> </div> </div> Но самый интересный эффект - это движение сначала с ускорение, а потом с замедлением. Именно так движутся объекты в жизни, поэтому данный эффект выглядит наиболее естественно. Тут мои познания в математике заканчиваются и приходится обращаться к гуглю, вот какую формулу я нагуглил: Math.pow(k, 2) * (3 - 2 * k); Давайте применим ее. Параметр назовем both: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.type = params.type ? params.type : 'accel'; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; var k = elapsedTime / self.duration; var result = self.from + (self.to - self.from) * self.calculate(k); result = self.fixResult(result); self.obj.style.cssText = self.attr + ': ' + result + self.units; if (k >= 1) { window.clearInterval(self.obj.interval); } }, 10); }, calculate: function(k) { if (this.type == 'accel') { return Math.pow(k, 2); } else if (this.type == 'decel') { return Math.sqrt(k); } else if (this.type == 'both') { // если параметр равен both return Math.pow(k, 2) * (3 - 2 * k); // движемся сначала с ускорением, а потом с замедлением } else { return k; } }, fixResult: function(num) { num = Math.round(num); if (this.from < this.to) { if (num > this.to) { num = this.to; } if (num < this.from) { num = this.from; } } else { if (num < this.to) { num = this.to; } if (num > this.from) { num = this.from; } } return num; } } Ну вот мы и реализовали все базовые виды анимации объекта в нашем аниматоре. В принципе, для ускорения не обязательно возводить коэффициент в квадрат, если возводить его в куб (или в четверную степень и т.д.), то ускорение будет более резким. То же само е можно применить и к замедлению - для более выраженного эффекта надо извлекать кубический корень (или корень червертой степени), для этого нужно возводить коэффициент в степень 1/3. Я ввел еще один параметр в аниматор, чтобы иметь возможность изменять выраженность эффектов ускорения и замедления: var Animate = { init: function(params) { this.obj = (typeof params.obj == 'string') ? document.getElementById(params.obj) : params.obj; this.power = params.power ? params.power : 2; this.type = params.type ? params.type : 'accel'; this.attr = params.attr ? params.attr : 'left'; this.units = params.units ? params.units : 'px'; this.duration = params.duration ? params.duration : 500; this.from = params.from; this.to = params.to; this.startTime = new Date().getTime(); this.move(); }, move: function() { var self = this; if (this.obj.interval) { window.clearInterval(self.obj.interval); } this.obj.interval = window.setInterval(function() { var elapsedTime = (new Date().getTime()) - self.startTime; var k = elapsedTime / self.duration; var result = self.from + (self.to - self.from) * self.calculate(k); result = self.fixResult(result); self.obj.style.cssText = self.attr + ': ' + result + self.units; if (k >= 1) { window.clearInterval(self.obj.interval); } }, 10); }, calculate: function(k) { if (this.type == 'accel') { return Math.pow(k, this.power); } else if (this.type == 'decel') { return Math.pow(k, 1 / this.power); } else if (this.type == 'both') { return Math.pow(k, this.power) * (3 - 2 * k); } else { return k; } }, fixResult: function(num) { num = Math.round(num); if (this.from < this.to) { if (num > this.to) { num = this.to; } if (num < this.from) { num = this.from; } } else { if (num < this.to) { num = this.to; } if (num > this.from) { num = this.from; } } return num; } } Ну вот мы и реализовали наш мини-фреймворк для анимации движения объектов. Что он умеет: 1) анимировать движение объекта по оси X или Y; 2) анимировать движение объекта с эффектами ускорения и замедления; 3) анимировать движения в пикселях или в процентах; 4) время анимации может изменяться по желанию пользователя; 5) аниматор имеет всего 3 обязательных параметра - id ноды или сама нода, начальная координата и конечная координата. Надеюсь что после прочтения этого урока вы научились создавать свои объекты, поняли принципы реализации больших фреймворков, поняли принципы анимации движения объектов в JavaScript и вообще почерпнули для себя много нового. Спасибо за внимание. Про вопросы, предложения, критику и лесть вы помните. P.S. Сайт, на котором я нашел основную формулу и формулу движения с ускорением и замедлением (easeInOut) - тут
    1 point
  11. Юзайте jquery и не занимайтесь ерундой.
    -1 points
This leaderboard is set to Kiev/GMT+02:00
×
×
  • 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