07. Event Model


1

FIXED:Ето решенията ми за BG Coder с старите ни любими var и for цикли като има и es6 едно елегантно решение с рекурсия :) Цък

Eто и решението DOM Operations Цък  като трябва да смените 'forEach' с "for(let i =0.....)" и "let" на "var" за да изкара 100/100 BG Coder! Добавих и jquery, защото е по правилно да се закачи един евент на целия selector, от колкото на всеки бутон по отделно.

06.DOM Operations: Цък

09.jQuery Overview: Цък




Отговори



1

Mерси колега!

Аз явно изобщо не мога да разбера желаното поведение, http://pastebin.com/U2JGzNdv  моя код прави това което аз разбрах - при кликане на някои от бутоните, в зависимост от това дали е на hide или show да скрива или показва content-a под него... Но от локалните минават 5, а в бгкодер 4... Твоя код очевидно минава всичко, само че като си го рънна в browser-a не прави абсолютно нищо...

Игнорирайте act функцията, отказах се да я оправя след като не мога да разбера условието :)


от cmdkick (120 точки)


1

Желаното поведение е: когато цъкнеш бутон да гледа след него елементите и ако намери елемент с  клас "content", който да е преди бутон след кликнатия бутон да прави нещо на тоя елемент с клас "content". Ако обаче не намери такъв елемент и стигне до бутон значи между двата бутона няма елемент с клас content и не трябва да правиш нищо, както и ако стигнеш до доло и няма повече елементи и не си намерил елемент с клас "content".

ОК, хора  оправено е вече, бах пропуснал в рекурсията return ма никой не казва :D а npm testa и Bgcoder си бяха ок....!!!!


от IliyaST (251 точки)

0
Като го рънна в браузър кода ти, последния ред с 3 бутона не работи. Също според мен , доколкото разбирам условието, на редовете, където има повече от един бутон, само последния преди контента трябва да работи (
  • If there isn't a .content element after the clicked .button and before other .button, do nothingIf there isn't a .content element after the clicked .button and before other .button, do nothing )
Аз имам същия проблем, в браузъра всичко работи по начина, по който го разбирам, но тестове 3 и 4 не минават. И кода на IliyaST  по същия начин неправи нищо в браузъра, но явно минава тестовете.

от didexe (122 точки)



1
Благодаря много. Можете ли все пак да погледнете този код и да ми кажете защо не мога да селектирам елементи  с class content. Код

от nivalen292 (273 точки)


-1
Значи else if (selector instanceof HTMLElement) {
      el = document.getElementsByTagName(selector.nodeName)[0];
    } е тоя елемент ти е мисля грешен..... как разбра че е първия ? може да имаш няколко тага примерно как ще разбереш кой ....Като цяло тоя ред ти е излишен защото се казва че ти е подаден конкретен елемент или id и ти трябва ако е id Просто да го потърсиш, а ако е конкретен да си продължиш......И мисля че след това не би трябвало д имаш грешка препоръчвам ви силно да се научите да дебъгвте :D

от IliyaST (251 точки)

1

Не му е това грешката, аз го подведох за този начин на решаване, наистина може и да не е първия елемент. После ми стана ясно,че подадения обект selector е валиден елемент и може да се ползва директно, но в контекста на задачата не е води до грешка. 

nivalen, според мен, проблема е във for цикъла,в който закачаш ивента, защото първо върти ,за да зададе стойности hide след това при click извиква функцията на ивената, но ползва i от цикъла, който не съотвества на елемента, който търсиш. 

Мисля,че ще по добре да си изкараш фунцкията отделно от закачането на ивента.

Ето така:

function solve() { return function (selector) { if (selector === null) { throw "error"; } if (typeof selector !== "string" && !(selector instanceof HTMLElement)) { throw "error"; } var el; if (typeof selector === "string") { el = document.getElementById(selector); } else if (selector instanceof HTMLElement) { el = document.getElementsByTagName(selector.nodeName)[0]; } //за закачане на метод на всички елементи с клас .button може да напаравиш така: var buttons = el.getElementsByClassName('button'), len = buttons.length; for (var i = 0; i < len; i++) { buttons[i].innerHTML = 'hide'; buttons[i].addEventListener('click', hidingElements, false); } //самия ивент ще изглежда така //1во --- късай ги от закачането, за да ти е по-лесно да се ориентираш. function hidingElements(event) { //този event, който го виждаш като аргумент е всъщност сочи към обекта, който е натиснат,и е по default //не е нужно да се подава някъде var target = event.target, // това ти е натиснатия бутон elementToChange = target.nextSibling; while (elementToChange.className !== 'content'){ elementToChange = elementToChange.nextSibling; } if(elementToChange.style.display === ''){ elementToChange.style.display = 'none'; target.innerHTML = 'show'; } else { elementToChange.style.display = ''; target.innerHTML = 'hide'; } } }; }

Ако имаш време погледни ето ТОВА


от svrakata (591 точки)



0

Може да е тъп въпроса, но в кой режим подаваме домашните -- Practice или Compete. Гледам, че на Compete има и някакви въпроси за отговаряне.

И едно решение в <30 реда от мен.




1
В Compete, иначе няма да си вземеш точките за домашното. Какви въпроси ти излизат, освен за студентския номер?

от deyan.nikolov (245 точки)

1

Бях се заблудил от това, че на страницата http://bgcoder.com/Contests#!/List/ByCategory/55/JavaScript-UI-DOM-Homework като задържиш върху въпросителната изписва: This contest has questions to be answered . Явно се е имало предвид въпроса за студ. номер.

Колега, благодаря, не знам защо бях решил, че трябва да пускам в Practice и щях да отърва точките...




1

Ето го и моето решение. В BgCoder ми дава 100/100, но локално не минава единия тест (expect to hide the next content on button click, and then show it again). Някой дали има идея защо?

function solve() { return function (element) { var selectedElement; var filteredButtonElementsFromSelectedElement; if (typeof (element) !== 'string' && (!(element instanceof HTMLElement))) { throw new Error('Element is neither string or html element') } if (typeof (element) === 'string') { selectedElement = document.getElementById(element); if (selectedElement === null) { throw new Error('Error'); } } else { selectedElement = element; } filteredButtonElementsFromSelectedElement = document.getElementsByClassName('button'); filteredButtonElementsFromSelectedElement = [].slice.apply(filteredButtonElementsFromSelectedElement); for (var but of filteredButtonElementsFromSelectedElement) { but.innerHTML = 'hide'; } document.addEventListener('click', changeVisibilityOnButtonClick); function findIfSiblingIsContent(element) { var sibling = element.nextElementSibling; if (sibling.className === 'content') { return sibling; } else { return null; } } function changeVisibilityOnButtonClick(event) { var targetButton = event.target; var sibling = targetButton; while (sibling.className !== 'content') { sibling = sibling.nextElementSibling; if (sibling.className === 'button') { break; } else if (sibling.className === 'content') { if (targetButton.innerHTML === 'hide') { targetButton.innerHTML = 'show'; sibling.style.display = 'none'; } else if (targetButton.innerHTML === 'show') { targetButton.innerHTML = 'hide'; sibling.style.display = ''; } } } } }; };


от mkanovski (552 точки)


1

Причината е, че закачаш EventListener-a директно на document обекта. Node няма такъв и следователно като се пуска event по време на тестовете той не прави нищо.

Като преместих добавянето на EventListener-a в ето този цикъл и минаха всички тестове при мен:

for (var but of filteredButtonElementsFromSelectedElement) { but.addEventListener('click', changeVisibilityOnButtonClick); but.innerHTML = 'hide'; }


от deyan.nikolov (245 точки)

1
Ясно! Мерси :)

от mkanovski (552 точки)


0

Здравейте, някой може ли да посочи къде бъркам, че си покривих главата от мъдруване, визуално го докарва ефекта (според описанието), хвърля грешки където има нужда и пак дава само 75% локално и в бгкодер...

function solve(){ return function (selector) { if (typeof selector === "string") { selector = document.getElementById(selector); if (!selector) { throw new Error("no element with such ID"); } } else if ( !(selector instanceof HTMLElement) ) { throw new Error("not an HTMLElement"); } var btns = selector.getElementsByClassName("button"); var contents = selector.getElementsByClassName("content"); for (var i = 0, len = btns.length; i < len; i += 1) { btns[i].textContent = "hide"; btns[i].addEventListener("click", function(event) { var that = event.target; var next = findNextContent(that); function findNextContent(target) { var next = target.nextElementSibling; if (!next || next.classList.contains('button')) { return null; } if (next.classList.contains('content')) { return next; } return findNextContent(next); } if (!next || !next.classList.contains('content')) { return; } if (next.style.display === "") { next.style.display = "none"; that.textContent = 'show'; } else { next.style.display = ""; that.textContent = 'hide'; } }); } }; };


от IvanS1991 (80 точки)


0

next.classList.contains('content') го промени на next.className==='content',

както и във findNextContent, явно трябва да търси, докато намери 'content' клас (или стигне края):

   if (!next || next.classList.contains('button')) {
            return null;
          }

да стане:

   if (!next) {
            return null;
          }

function solve(){ return function (selector) { if (typeof selector === "string") { selector = document.getElementById(selector); if (!selector) { throw new Error("no element with such ID"); } } else if ( !(selector instanceof HTMLElement) ) { throw new Error("not an HTMLElement"); } var btns = selector.getElementsByClassName("button"); var contents = selector.getElementsByClassName("content"); for (var i = 0, len = btns.length; i < len; i += 1) { btns[i].textContent = "hide"; btns[i].addEventListener("click", function(event) { var that = event.target; var next = findNextContent(that); function findNextContent(target) { var next = target.nextElementSibling; if (!next) { return null; } if (next.className ==='content') { return next; } return findNextContent(next); } if (!next || !next.className ==='content') { return; } if (next.style.display === "") { next.style.display = "none"; that.textContent = 'show'; } else { next.style.display = ""; that.textContent = 'hide'; } }); } }; };


от nefto (77 точки)

0

Thanks a lot, nefto. И аз се бях зачукал с това .classList.contains()


от ndvalkov (60 точки)