вторник, 1 мая 2012 г.

Локализация области действия скрипта Mathjax

В разрабатываемом приложении, которое позволяет студентам интерактивно решать задачи по линейной алгебре, студент вводит части своего решения (формулы) с помощью специального элемента управления, который для краткости называется шагом студента. Для студентов предусмотрено два вида интерфейса ввода шагов: "легкий" и "трудный". В легком интерфейсе студенту предоставляется шаблон("скелет") формулы, который он может заполнять математическими символами с помощью drag-and-drop.

Дмитрием был разработан тестовый пример, в котором на странице располагалось текстовое представление шаблона формулы (на рис - 1), математические символы, которые можно тащить и бросать в шаблон (2), сам шаблон, сгенерированный на основе текстового представления (3), и динамически генерирующееся скриптом Mathjax представление измененного шаблона (4).



А вот как выглядел этот пример при частично заполненной формуле:


Далее выяснилось, что если на html-странице расположено несколько шаблонов формул (а они в разрабатываемом приложении все заполняются математическими символами из одной и той же таблицы), то при заполнении очередного шаблона "гадится" генерирующееся mathjax'ом представление других шаблонов.

В тестовом примере обращение к элементам на странице шло по классу CSS. Например:


Для решения этой проблемы создала тестовый пример с двумя шаблонами для заполнения. 
Всем значимым элементам html дала id, при этом id назначала так:

То есть, у одинаковых по функциональному назначению элементов id отличались только номерами в конце. Функцию, которая обрабатывает бросание математического символа на шаблон формулы, изменила так: То есть, алгоритм был такой: получаем идентификатор шаблона, куда сброшен математический символ. 
Из него получаем номер шаблона (1 или 2), далее формируем идентификатор визуального представления, которое должно обновиться и просим Mathjax обновить только одинhtml  элемент -- с этим идентификатором.

В процессе решения этой проблемы помогла страница, которую порекомендовал Дмитрий.

13 комментариев:

  1. Анонимный8 июня 2012 г., 19:15

    Здравствуйте Наталья. Искал решение своей задачи и наткнулся на эту страничку. Возможно Вы сможете мне что то посоветовать.

    Задача определить X. Имеем Y = 4 и Z = 2. И знаем что X = Y / Z. - все это задача для расчета. НАША задача написать программу, которая бы представила оформленным решение этого расчета. В итоге мы должны получить следующее:

    X = (Y / Z) = (4 / 2) = 2

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

    Вопрос в том как это сделать и куда? я думал о том что бы расчет делать в консольной программе а выводить в Word. Но как это сделать не нашел. Что посоветуете?

    ОтветитьУдалить
  2. Здравствуйте, Анонимный!
    Это реальная задача - например, вы пытаетесь сделать онлайн решатель для домашек или задача на зачет по программированию?

    ОтветитьУдалить
  3. Извините, невнимательно прочитала вопрос.

    >>Вопрос в том как это сделать и куда? я думал о >>том что бы расчет делать в консольной >>программе а выводить в Word. Но как это сделать не нашел.

    По-видимому, это все-таки задача на зачет.
    "Парсинг" выражения рекомендую делать с помощью аппарата регулярных выражений. Регулярные выражения есть для многих языков. Если собираетесь делать программу как настройку к MS Office, тогда см. в интернете "регулярные выражения VBA". Удачи!

    ОтветитьУдалить
    Ответы
    1. Анонимный10 июня 2012 г., 12:09

      Спасибо за ответ, извините, что не сразу ответил. Искал про регулярные выражения, честно говоря, ничего конкретного не нашел. Можете как нибудь сузить область поиска? это бы очень сильно помогло.
      Вы говорите о регулярных выражениях ВБА, а нельзя ли сделать тоже самое для офиса через c#? как то в этом у меня больше опыта.
      И еще такой вопрос, возможно ли открыть документ word, и получить код содержимого на листе, текста и формул, и просто подставлять заместо значений переменные?

      Удалить
  4. Странно, что вы знаете C#, а задаете такие вопросы (без обид) :)

    >>И еще такой вопрос, возможно ли открыть документ word, и получить код содержимого на листе, текста и формул, и просто подставлять заместо значений переменные?

    Ну вот ссылка навскидку.

    http://nullpro.info/2011/kak-otkryvat-i-izmenyat-dokumenty-word-iz-c/

    >>Искал про регулярные выражения, честно говоря, ничего конкретного не нашел. Можете как нибудь сузить область поиска?

    Регулярные выражения в вашей задаче полезно использовать для того, чтобы искать фрагменты вида Y/Z и заменять их на то, что вам нужно. Я в свою очередь, не очень понимаю, что вам непонятно про регулярные выражения.

    Если вы их никогда не применяли, попробуйте для начала немного о них почитать какие-то вводные статьи и сделать простую подзадачку вида: Дана строка, которая может содержать латинские буквы (A-Z), цифры (0-9) и арифметические знаки (+-*=/). Составить регулярное выражение для поиска фрагментов вида .../...где вместо ... может быть любая латинская буква.

    ОтветитьУдалить
  5. Попробуйте описать задачу с чисто житейской точки зрения. Типа: куда сначала лезет пользователь вашей программы, что он видит, какие данные вводит, что должен получить (увидеть) на выходе. Можете описать постановку в открытом google-документе и кинуть сюда ссылку. Желательно с картинками. Возможно, вы сформулировали задачу слишком неточно, я ее поняла по-своему (не так, как надо) и увожу вас "в темные леса".

    ОтветитьУдалить
  6. Анонимный11 июня 2012 г., 20:14

    Наталья, не ругайтесь, я еще не все знаю))

    В Вашей ссылке, это какой то больно сложный способ. Я нашел, как это сделать по двум статьям:

    Создание документа и добавление текста:
    http://msdn.microsoft.com/ru-ru/library/cc442985.aspx

    и

    Замена текста
    http://msdn.microsoft.com/ru-ru/library/f65x8z3d.aspx

    , но в первой ссылке у меня не получается добавить текст. Когда я компилирую, открывается пустой документ и там нет теста, ни который я добавил с помощью конструктора, ни с помощью кода. Вот тут я и остановился, я не знаю почему. Это на данный момент главный вопрос!

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

    Что касается с описать с житейской точки зрения. Пользователь вводит только начальные данные (в моем примере Y и Z). Формула для расчета стандартная, с ней пользователь не работает. На выходе он должен получить формулу с подставленными туда, введенными значениями (Y, Z) и ответ рассчитанный по этой формуле.

    ОтветитьУдалить
  7. >>Вот тут я и остановился, я не знаю почему. Это на данный момент главный вопрос!

    С этим вопросом не ко мне :) Или к самому себе, или к преподавателю, или на специализированный форум по C#.

    >>Потому что я не знаю, как записать код формулы в нормальном виде.

    http://social.msdn.microsoft.com/Forums/en/vsto/thread/a32c4714-f2d7-458c-a31f-696f6de64a0a

    ОтветитьУдалить
  8. А вообще, все же советую поизучать VBA. Вы сначала потратите дополнительное время на изучение, но когда начнете реализовывать задачу, реализовать ее будет В РАЗЫ проще.

    ОтветитьУдалить
  9. Анонимный22 июня 2012 г., 14:10

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

    ОтветитьУдалить
  10. Анонимный22 июня 2012 г., 14:11

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Xml.Linq;
    using Microsoft.Office.Tools.Word;
    using Microsoft.VisualStudio.Tools.Applications.Runtime;
    using Office = Microsoft.Office.Core;
    using Word = Microsoft.Office.Interop.Word;



    namespace WordDocument3
    {
    // Создаем класс в котором осуществляется решение и указание
    // на замену переменных

    public partial class Решение
    {

    // Объявляем перменные которую нужно заменить и на которую нужно заменить
    public const int x2 = 901;
    public const int z2 = 900;

    // Функция которая должна создавать объект класса ThisDocument и осуществлять
    // в нем метод замены ThisDocument_Startup они описаны ниже
    // Эта конструкция как раз и не работает, никакой замены не происходит.
    void Main()
    {
    ThisDocument A = null;
    A.x = x2.ToString();
    A.z = z2.ToString();
    }
    // Тоже с другими переменными
    public const int x1 = 801;
    public const int z1 = 800;

    void Main1()
    {
    ThisDocument A = null;
    A.x = x1.ToString();
    A.z = z1.ToString();
    }

    }
    public partial class ThisDocument
    {
    public string x;
    public string z;

    // Метод который выполняется при открытии документа
    public void ThisDocument_Startup(object sender, System.EventArgs e)
    {

    // Код, который ищет и заменяет
    Word.Find findObject = Application.Selection.Find;
    findObject.ClearFormatting();
    findObject.Text = "@@" + z;
    findObject.Replacement.ClearFormatting();
    findObject.Replacement.Text = x;

    object replaceAll = Word.WdReplace.wdReplaceAll;
    findObject.Execute(ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref replaceAll, ref missing, ref missing, ref missing, ref missing);
    }


    private void ThisDocument_Shutdown(object sender, System.EventArgs e)
    {
    }



    #region VSTO Designer generated code

    ///
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    ///
    private void InternalStartup()
    {
    this.Startup += new System.EventHandler(ThisDocument_Startup);
    this.Shutdown += new System.EventHandler(ThisDocument_Shutdown);
    }

    #endregion

    }

    }

    ОтветитьУдалить