1. JavaScript / Говнокод #20013

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    function saveQuestion() {
    	var questionContent = {};
    	var questionResult = {};
    	switch(questionFields.attr('class')) {
    		case 'check-question':
    			questionResult.text = questionFields.children('.question-text')[0].innerText;																				
    			questionResult.type = 'check';
    			questionResult.answers = [];
    			[].forEach.call(questionFields.children('.answer-preview'), function(answerElement, i, arr) {
    				var answer = {};
    				answer.text = $(answerElement).children('.answer-text')[0].innerText;
    				answer.right = ($(answerElement).children('.answer-check')[0].checked) ? 1 : 0;
    				answer.weight = (!answer.right) ? $(answerElement).children('.answer-weight')[0].getPosition() : 1;
    				answer.weight = (answer.weight > 0 && answer.weight <= 1) ? answer.weight : 0;
    				questionResult.answers.push(answer);
    			});
    			
    			if (checkQuestionCorrect(questionResult)) {
    				questionResult= JSON.stringify(questionResult);
    				questionContent = JSON.parse(questionResult); //клонируем объект
    				[].forEach.call(questionContent.answers, function(answer, i, answers) { delete answer.right; delete answer.weight; });
    				questionContent = JSON.stringify(questionContent);
    				console.log('result: ' + questionResult);
    				console.log('content: ' + questionContent);
    				net.addQuestion(loID, questionContent, questionResult, function(r){
    					$('.add-question').slideUp(200, function(){
    						$('.add-question-row').remove();
    						openLOPreview(loID);
    					});
    				});
    			}
    		break;	
    		
    		case 'input-question':
    			var highlights = highlighter.highlights;
    			questionResult.type = 'input';
    			questionResult.text = $('#question-text-area').get(0).innerText;
    			questionResult.answers = [];
    			for (i = 0; i < highlights.length; i++) {
    				var answer = {};
    				answer.id = highlights[i].id;
    				answer.posStart = highlights[i].characterRange.start;
    				answer.posEnd = highlights[i].characterRange.end;
    				answer.text = highlights[i].answerText;
    				answer.strict = ('strict' in highlights[i]) ? highlights[i].strict : true;
    				questionResult.answers.push(answer);
    			}
    			questionResult.answers.sort(function(a, b){ return a.posStart - b.posStart; });
    			questionResult.serializedHighlight = highlighter.serialize();
    			questionResult = JSON.stringify(questionResult);
    			questionContent = JSON.stringify(questionContent);
    			
    			net.addQuestion(loID, questionContent, questionResult, function(r){
    				$('.add-question').slideUp(200, function(){
    						$('.add-question-row').remove();
    						openLOPreview(loID);
    					});
    			});	
    		break;
    		
    		default: break;
    	}							
    }

    Моя дипломная работа по теме "тестирование студентов". Конструктор тестов, обработчик кнопки сохранения вопроса. Используются библиотеки jQuery и Rangy (для работы с выделением текста).

    Запостил: cotheq, 16 Мая 2016

    Комментарии (40) RSS

    • Это случаем не для ондроида?
      Ответить
    • [].forEach

      Штоэта?
      Ответить
      • Гэта ЭКМАскрыпт пяць: http://caniuse.com/#search=forEach
        Ответить
        • гамон!
          Ответить
        • И нахуя foreach вызывать у пустого массива? Он же не вызовется ни разу.

          //Кэп, блядь.
          Ответить
          • Вызов forEach у пустого массива выглядит так:
            [].forEach(function(){do_something;});


            В ГК же вызова нет: мы получаем ссылку на метод forEach, а для него делаем call с непустым массивом.

            Короче, вот это вот:
            [].forEach.call(questionFields.children('.answer-preview'), function(){do_something});
            эквивалентно следующему:
            questionFields.children('.answer-preview').forEach(function(){do_something});


            Кэп.
            Ответить
            • Ах вот оно что. Но нахуя это так писать?

              В питоне тоже можно.

              In [2]: str.split('a b c')
              Out[2]: ['a', 'b', 'c']
              
              In [3]: 'a b c'.split()
              Out[3]: ['a', 'b', 'c']


              Но! Так уже нельзя.

              In [4]: "".split('a b c')
              Out[4]: ['']
              Ответить
              • Действительно. У меня даже через «магические» методы не получилось сделать аналог JS. Вот так работает:
                str.split.__call__('a b c')

                А вот так уже нет:
                "".split.__call__('a b c')
                Ответить
                • Впитоне методы биндятся.
                  Ответить
                  • То есть "".split в JS — это просто ссылка на метод split объекта типа строка, а впитоне — это метод split с уже привязанным аргументом ""?
                    Ответить
                    • In [9]: class A(object):
                         ...:     def method(self):
                         ...:         pass
                         ...:
                      
                      In [10]: A().method
                      Out[10]: <bound method A.method of <__main__.A object at 0x016A42F0>>
                      
                      In [11]: A.method
                      Out[11]: <unbound method A.method>
                      
                      In [12]: A.method()
                      ---------------------------------------------------------------------------
                      TypeError                                 Traceback (most recent call last)
                      <ipython-input-12-e47745f2c05a> in <module>()
                      ----> 1 A.method()
                      
                      TypeError: unbound method method() must be called with A instance as first argument (got nothing instead)
                      
                      In [15]: A.method(A())
                      
                      In [16]: A().method(A())
                      ---------------------------------------------------------------------------
                      TypeError                                 Traceback (most recent call last)
                      <ipython-input-16-e448cf329735> in <module>()
                      ----> 1 A().method(A())
                      
                      TypeError: method() takes exactly 1 argument (2 given)
                      Ответить
                      • А можно отбиндить, если уже прибиндили?
                        Ответить
                        • Хз :) Загугли. А зачем?

                          obj.__class__ - получаем класс объекта.
                          Ответить
                          • Уже раскопал. Так работает:
                            "".__class__.split('a b c')

                            И так тоже:
                            "".__class__.split.__call__('a b c')


                            А можно как-нибудь от "".split отвязать аргумент ""?
                            Ответить
                            • >Хз :) Загугли. А зачем?
                              Ответить
                            • У связанного метода есть поле __self__, указывающее на связанный объект.
                              Ответить
                              • Не помогло: у объекта "" нет поля __self__, а "".split.__self__ указывает не на отвязанный split, а на "". Т. е. можно писать бесконечные цепочки вида something.split.__self__.split.__self__. split.__self__, а аналога JS так и не получим.
                                Ответить
                                • "".split.__self__.__class__.split

                                  Можно даже круче сделать,

                                  [code language=python]
                                  def unbind(method):
                                  return method.__self__.__class__.__dict__[method.__name__]
                                  [/code]
                                  Ответить
                                  • Блядь, bbcode не сработал.
                                    def unbind(method):
                                         return method.__self__.__class__.__dict__[method.__name__]
                                    Ответить
                                    • Можно, но зачем? Уебанскее != круче.
                                      Ответить
                                      • Я нежно люблю питон именно за вот эту возможность. "Возьму-ка я простенький скриптовый язычок... ...ой, тут можно обойти проблему через рефлексию... ...блядь, что за плюсы в моём коде?"
                                        Ответить
                                        • Уебаны, пишущие напитоне как на %языкпрограммирования%, не нужны. Чемодан-вокзал-%языкпрограммирования%
                                          Ответить
                                          • Чемодан-вокзал-питон? Это с тобой в одном купе ехать? Нафиг-нафиг.
                                            Ответить
                                          • > Уебаны, пишущие напитоне как на %языкпрограммирования%

                                            Шо ты кипятишься, как агицын паровоз?
                                            Ответить
                                            • Заебали люди, делающие сишный апи в языке, где есть именованные/необязательные параметры. Вот это вот строк на 10
                                              obj = Class()
                                              obj.set_pizda(pizda)
                                              obj.set_jigurda(1)
                                              Ответить
                                  • Спасибо! Это то, что нужно!
                                    Ответить
              • > Ах вот оно что. Но нахуя это так писать?
                Для разнообразия, в JS есть несколько коллекций, которые очень похожи на массивы (есть 0, 1, 2, ..., length), но таковыми не являются. Например, NodeList, Arguments. В случае, если эти коллекции не требуется менять, можно вполне рассматривать их как обычные массивы, но forEach, map, filter у них нет, потому приходится заимствовать их у обычного массива.
                Ответить
                • И почему у них нет этих методов? Что мешало унаследоваться от массива? И почему [].forEach глотает их? В питоне вылетает исключение. Из примера выше

                  In [18]: A.method(1)
                  ---------------------------------------------------------------------------
                  TypeError                                 Traceback (most recent call last)
                  <ipython-input-18-0e2198a35e35> in <module>()
                  ----> 1 A.method(1)
                  
                  TypeError: unbound method method() must be called with A instance as first argument (got int instance instead)


                  Ответить
                  • Либо недодумали - не знали, что когда-то будут запиливать ES5.1 со всякими map/forEach, либо передумали - какие-нибудь модифицирующие функции могли поломать логику.
                    А в JS методы - те же функции, которые иногда используют неявный аргумент this. Работает утиная типизация. Если this имеет структуру, которую требует функция, то никто ничего не заметит.
                    Если метод не упоминает свой this, его спокойно можно брать у объекта и использовать как обычную функцию. Привязывать объект к функции нужно явно.
                    Ответить
          • P.S. Это классика! Это знать надо:
            http://javascript.ru/function/call

            https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/call

            Ещё есть bind и apply.
            Ответить

    Добавить комментарий