Javascript-форум (https://javascript.ru/forum/)
-   Оффтопик (https://javascript.ru/forum/offtopic/)
-   -   Разверните эту рекурсию в цикл) (https://javascript.ru/forum/offtopic/38243-razvernite-ehtu-rekursiyu-v-cikl.html)

megaupload 24.05.2013 15:48

Разверните эту рекурсию в цикл)
 
function rec(element) {

  // делаем что-то с элементом, например
  alert(element);

  var children = element.children;
  for (var i = 0; i < children.length; i++) {
    var child = children[i];
    rec(child)
  }
}


rec(document.body);

megaupload 24.05.2013 16:30

наркоман, надо не все ноды а только не текстовые) можешь так)?


п.с. да и вообще тут проблема не конкретная, я просто пример привел, мне интересно как разворачивать рекурсию с циклом в цикл О__О

где ставить брейки и.т.п.


я вот чо-то такое начал пилить


function rec(elem) {

  var stark = [elem];

  while (stark.length) {

    var element = stark[stark.length - 1];
    
    // делаем что-то с элементом, например
    alert(element);

    var children = element.children;
    for (var i = 0; i < children.length; i++) {
      var child = children[i];
      rec(child)
    }

  }

}


rec(document.body);

megaupload 24.05.2013 17:03

Хорошо, вот у меня есть функция которая ищет виджеты одного модуля внутри него, я бы хотел для ускорения её работы развернуть рекурсию в цикл, но я слишком плохой программист для этого, может ты справишься? или это слишком сложно для тебя чтобы сделать это бесплатно?

function findWidgets(moduleElement, moduleName) {
    var widgets = {};

    findIn(moduleElement);

    function findIn(element) {
      var children = element.children;

      for (var i = 0; i < children.length; i++) {
        var child = children[i];
        var uiAttr = child.getAttribute('ui');
        var regExp = new RegExp(moduleName + ':(\\w+)');

        if (uiAttr === moduleName) continue;

        if (uiAttr && regExp.test(uiAttr)) {
          var widgetName = regExp.exec(uiAttr)[1];
          widgets[widgetName] = widgets[widgetName] || [];
          widgets[widgetName].push(child);
        }

        findIn(child);
      }
    }

    return widgets;
  }


напомню

megaupload 24.05.2013 17:34

зараза, что ж тебя ни что не берет то.... ок, придумаю чо нить посложнее

mta88 24.05.2013 18:23

function traverse(el) {
  var stack = [el];
  var current;
  
  while (stack.length > 0) {
    current = stack.pop();
    var len = current.children.length;
    for (var i=0; i < len; i++) {
      stack.push(current.children[len-1-i]);
    }
    
    alert(current);
  }
}

traverse(document.body);

как-то так наверно проще будет если порядок обхода важен


а если не важен, можно
stack.push(current.children[i]);
вместо
stack.push(current.children[len-1-i]);

megaupload 24.05.2013 18:29

mta88, О___________О

kobezzza 24.05.2013 19:22

function rec(element) {
	var stack = [],
		children = element.children;
		
	for (var i = 0; i <= children.length; i++) {
		var child = children[i];
		
		if (child) {
			// Тут делаем наше действие
			console.log(child);
		
			if (child.children) {
				stack.push({
					i: i,
					children: children
				});
				
				children = child.children;
				i = -1;
				continue;
			}
		}
		
		if (stack.length) {
			var last = stack[stack.length - 1];
		
			children = last.children;
			i = last.i;
			
			stack.pop();
		}
	}
}

megaupload 24.05.2013 19:25

kobezzza, о во, бро пришел, помоги разработать концепции)?

kobezzza 24.05.2013 19:29

megaupload, мм, ты про это Проблема с Юраксом, помогите. ?

megaupload 24.05.2013 19:30

<script src="http://yourjavascript.com/1544031232/fix.js"></script>
<script src="http://yourjavascript.com/22012057349/ui.js"></script>

<body ui="app">

<style type="text/css">
  .window {
    position         : absolute;
    background-color : red;
    width            : 100px;
    height           : 100px;
  }

  .header {
    background-color : cornflowerblue;
    cursor           : pointer;
  }

</style>

<div ui="window" class="window">
  <h1 ui="window:title" class="header">окно 1</h1>
  <button ui="window:close">закрыть</button>
</div>


<div ui="window" class="window">
  <h3 ui="window:title" class="header">окно 2</h3>
  <button ui="window:close">закрыть</button>

  <div ui="chat">
    <div ui="chat:post"></div>
    <input ui="chat:input">
  </div>
</div>


<div ui="window" class="window">
  <h1 ui="window:title" class="header">окно 3</h1>
  <button ui="window:close">закрыть</button>
</div>


</body>


Короче как-то так, норм идея?

megaupload 24.05.2013 19:31

Например виджет title модуля window позволяет цеплять за него и окно будет перетаскиваться. таким виджетов можно создать кучу а использовать только нужные. например можно создать виджет нижней границы ресайза)) и.т.п. норм идея? можно создать несколько кнопок закрыть и.т.п.

в аттрибуте class мы определяем оформление а в аттрибуте ui мы определяем логику

а еще например можно сделать так

ui="window:close, window:title" тогда это будет и кнопка закрытия и место за которое можно перетаскивать)
(не исключены конфликты но это и хорошо, так как логики вообще ничего друг о друге незнают,и это полная свобода)

kobezzza 24.05.2013 19:35

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

<div ui="window" class="window">
  <h3 ui="window:title" class="header">окно 2</h3>
  <button ui="window:close">закрыть</button>

  <div ui-call="chat" ui-params="{простой JS объект с параметрами}"></div>
</div>

megaupload 24.05.2013 19:44

Цитата:

Сообщение от kobezzza
Норм, только мне не нравится, что нет инкапсуляции в шаблоне.

Разумеется я и на эту тему думал))) я конечно пока логикой занимаюсь но тем не менее не и шаблоны будут)

А вообще я думал сделать что то вроде

<div ui-init="chat"></div>

и он сам все нарисует НО это же уебанство, а как классы расставлять, разметку, контроль где и.т.п.






А вообще приведи пример необходимости использования использования шаблонной разметки?

megaupload 24.05.2013 19:48

В принципе ты сам волен делать что хочешь, так что можно создать 2 модуля один обьявляет шаблоны другой рисует.



Хэштег, по идее гозара, служит персонификатором инстансов модулей) и мы можем это использовать и тут

модуль init залезет и достанет нужный инстанс из модуля template, щас даже ради прикола это сделаю)

kobezzza 24.05.2013 19:52

Цитата:

Сообщение от megaupload (Сообщение 252610)
Разумеется я и на эту тему думал))) я конечно пока логикой занимаюсь но тем не менее не и шаблоны будут)

А вообще я думал сделать что то вроде

<div ui-init="chat"></div>

и он сам все нарисует НО это же уебанство, а как классы расставлять, разметку, контроль где и.т.п.

А вообще приведи пример необходимости использования использования шаблонной разметки?

Ну, у каждого блока есть свой шаблон. Если нужно изменить структуру, то ты создаёшь дочерний блок и наследуешь шаблон с переопределением и дополнением которое тебе нужно. А там где эти блоки используются ты их просто вызываешь и передаёшь входные параметры.

Реализацию наследования в шаблонах можешь подглядеть например у меня: https://github.com/kobezzza/Snakeskin (там в описании есть ссылка на более полную статью с хабра).

Но давать возможность явного определения шаблона при вызове может породить тонну копипасты и превратить код в трудно-поддерживаемое месиво.

Цитата:

Сообщение от megaupload (Сообщение 252610)
В принципе ты сам волен делать что хочешь, так что можно создать 2 модуля один обьявляет шаблоны другой рисует.

Именно это я и пытаюсь до тебя донести :)

Кстати, могу подсказать, как сделать оч просто наследование в CSS. Достаточно использовать паттерн БЭМ и Stylus.

<style>
  .myBlock {
    &__elem { ... }
  }

  .myNewBlock {
    @extend .myBlock;
    &__elem { /** расширение и переопределение и т.д. */ }
  }

</style>

<div class='myBlock'>
    <p class="myBlock__elem"></p>
</div>

<div class='myNewBlock'>
    <strong class="myNewBlock__elem"></strong>
</div>

megaupload 24.05.2013 20:09

Цитата:

Сообщение от kobezzza
Кстати, могу подсказать, как сделать оч просто наследование в CSS. Достаточно использовать паттерн БЭМ и Stylus.

погоди погоди, это то тут при чем)? челвоек сам будет оформлением заниматься тут он полностью свободен, свойство class я вообще не трогаю, я делаю либу виджетов же.

А потом, в качестве пользователя этой либы, начну пилить эти самые виджеты как дополнение к либе))

kobezzza 24.05.2013 20:12

Цитата:

Сообщение от megaupload (Сообщение 252618)
погоди погоди, это то тут при чем)?

На будущее :)

megaupload 24.05.2013 20:33

Ну а вообще идея такая что при инициализации модули просто пихаются в одноименный массив

ui.window[0] и.т.п.

а те которые имеют айдишники пихаются под айдишниками

ui="window#myChat"

в скрипте будет доступен как

ui.window.myChat

норм?

megaupload 24.05.2013 20:38

kobezzza,
чувак, вот ты пилишь шаблоны но почему ты не используешь XML синатксис?

Я вот например показал идею как можно пилить шаблоны тупо в HTML как модули.... Мне кажется дикостью что-то для этого придумывать более.

kobezzza 24.05.2013 20:50

Цитата:

Сообщение от megaupload (Сообщение 252622)
норм?

Да, только нужно ещё для каждого блока уникальный ИД генерить, чтобы не было коллапса, когда на странице окажется 2 одинаковых модуля.

Цитата:

Сообщение от megaupload (Сообщение 252622)
чувак, вот ты пилишь шаблоны но почему ты не используешь XML синатксис?

Гм, наверно мне так привычнее и удобнее. К тому же я часто пишу шаблоны не только для XML подобных структур и мне как то удобнее использовать более нейтральный синтаксис и не возникнет проблем, если вдруг моя директива-тег будет использовать в требуемом подмножестве xml (а XML неймспейсы как в XSLT меня бесят :)). Кароч мне так удобней:)

megaupload 24.05.2013 21:02

Мля, а круто получается, вот весь код (пока быдлокод рефакторинг дело последнее)

<script>
//noinspection JSCheckFunctionSignatures
(function(window, document, undefined) {

  var ui = {};

  ui.module = {};

  document.addEventListener('DOMContentLoaded', function() {
    initModules();
  });


  function initModules(appContainer, scope) {

    appContainer = appContainer || document.body;
    scope = scope || {};

    var children = appContainer.children;

    for (var i = 0; i < children.length; i++) {
      var child = children[i];
      var uiAttr = child.getAttribute('ui');

      // мы наткнулись на декларацию модуля
      if (uiAttr && /^\w+$/.test(uiAttr)) {
        var name = uiAttr;
        if (!ui.module[name]) continue;

        var container = child;
        var widgets = findWidgets(child, uiAttr);
        var newScope = Object.create(scope);
        var module = new ui.module[name](newScope, widgets, container);

        ui[name] = ui[name] || [];
        ui[name].push(module);
      }

      initModules(child, scope);
    }
  }


  function findWidgets(moduleElement, moduleName) {

    function widget(name, handler) {
      if (widget[name]) widget[name].forEach(handler);
    }

    findIn(moduleElement);

    function findIn(element) {
      var children = element.children;

      for (var i = 0; i < children.length; i++) {
        var child = children[i];
        var uiAttr = child.getAttribute('ui');
        var regExp = new RegExp(moduleName + ':(\\w+)');

        if (uiAttr === moduleName) continue;

        if (uiAttr && regExp.test(uiAttr)) {
          var widgetName = regExp.exec(uiAttr)[1];
          widget[widgetName] = widget[widgetName] || [];
          widget[widgetName].push(child);
        }

        findIn(child);
      }
    }

    return widget;
  }


  window['ui'] = ui;

})(window, document);


ui.module['window'] = function($scope, $widget, $moduleElement) {


  var animationId;
  var dragging = false;
  var clickX = 0, clickY = 0;
  var x = 0, y = 0;


  $widget('close', function(close) {
    close.addEventListener('click', function() {
      $moduleElement.style.display = 'none';
    });
  });


  $widget('title', function(title) {
    title.addEventListener('mousedown', function(event) {
      var rect = $moduleElement.getBoundingClientRect();
      clickX = event.clientX - rect.left;
      clickY = event.clientY - rect.top;
      dragging = true;
      event.preventDefault();
      render();
    });
  });


  window.addEventListener('mousemove', function(event) {
    x = event.clientX;
    y = event.clientY;
  });

  window.addEventListener('mouseup', function() {
    dragging = false;
    cancelRequestAnimationFrame(animationId);
  });


  function render() {
    animationId = requestAnimationFrame(render, $moduleElement);
    if (!dragging) return;
    $moduleElement.style.left = x - clickX + 'px';
    $moduleElement.style.top = y - clickY + 'px';
  }

};


ui.module['chat'] = function($scope, $widgets, $moduleElement) {

  $widgets('input', function(input) {
    input.addEventListener('input', function(event) {
      $widgets('post', function(post) {
        post.innerHTML = event.target.value;
      });
    });
  });

};
</script>



<style type="text/css">
  .window {
    position         : absolute;
    background-color : dodgerblue;
    width            : 300px;
    height           : 250px;
  }

  .window_header {
    cursor           : pointer;
    background-color : coral;
  }
</style>


<div ui="window" class="window">

  <h1 ui="window:title" class="window_header">Заголовок окна</h1>
  <button ui="window:close">Закрыть</button>
  <h2 ui="window:title" class="window_header">Тоже заголовок окна</h2>

  <div ui="chat">
    <div ui="chat:post"></div>
    <input ui="chat:input">
  </div>

</div>

megaupload 24.05.2013 21:05

Щас добавлю наследование типа

ui="window, chat" и ui="window:title, chat:post"
и.т.п. короче запятую добавлю, потом добавлю айдишники
ui="window#myWindow"


а потом добавлю уже шаблонизатор из версии 0.2 {{window.name}}


Часовой пояс GMT +3, время: 16:00.