我需要保留data-tinymce html标记中的 struct 以传递给一个javascript函数,但不知何故没有保留该 struct ,这导致了该javascript函数中的方法失败.

它的 struct 是

{
  event_root: null,
  selector: ".tinymce",
  menubar: "file edit view insert format tools table help",
  toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
  toolbar_mode: "sliding",
  contextmenu: "link image table",
  quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
  plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
  promotion: false,
  autosave_ask_before_unload: true,
  autosave_interval: "30s",
  autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
  autosave_restore_when_empty: true,
  autosave_retention: "30m",
  image_caption: true,
  image_advtab: true,
  image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}

我有一个由助手函数生成的链接,该函数通过data-tinymce html属性传递此 struct ,代码如下

  # This method creates a link with `data-id` `data-fields` attributes. These attributes are used to create new instances of the nested fields through Javascript.
  def link_to_add_fields(name, f, association)
    new_object = f.object.send(association).klass.new

    # Saves the unique ID of the object into a variable.
    # This is needed to ensure the key of the associated array is unique. This is makes parsing the content in the `data-fields` attribute easier through Javascript.
    # We could use another method to achive this.
    id = new_object.object_id

    #tinymce_config = tinymce :try
    tinymce = CcsCms::CustomPage::ConfigTinymce.get_tiny_config_for_js("try")
    #tinymce = "<%=tinymce(:try)%>"
    # https://api.rubyonrails.org/ fields_for(record_name, record_object = nil, fields_options = {}, &block)
    # record_name = :page_sections
    # record_object = new_object
    # fields_options = { child_index: id }
    # child_index` is used to ensure the key of the associated array is unique, and that it matched the value in the `data-id` attribute.
    # `page[page_sections_attributes][child_index_value][_destroy]`
    fields = f.fields_for(association, new_object, child_index: id) do |builder|
        # `association.to_s.singularize + "_fields"` ends up evaluating to `page_sections_fields`
        # The render function will then look for `views/pages/_page_sections_fields.html.erb`
        # The render function also needs to be passed the value of 'builder', because `views/pages/_page_sections_fields.html.erb` needs this to render the form tags.
      render(association.to_s.singularize + "_fields", form: builder)
    end

    # This renders a simple link, but passes information into `data` attributes.
    # This info can be named anything we want, but in this case we chose `data-id:` and `data-fields:`.
    # The `id:` is from `new_object.object_id`.
    # The `fields:` are rendered from the `fields` blocks.
    # We use `gsub("\n", "")` to remove anywhite space from the rendered partial.
    # The `id:` value needs to match the value used in `child_index: id`.
    link_to(
      name,
      "#",
      class: "add_fields",
      data: {
        tinymce: tinymce, #.to_json.html_safe,
        id: id,
        fields: fields.gsub("\n", ""),
      },
    )
  end

此链接生成的html为

<a class="add_fields" data-tinymce="{
  event_root: null,
  selector: &quot;.tinymce&quot;,
  menubar: &quot;file edit view insert format tools table help&quot;,
  toolbar: [&quot;undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist&quot;,&quot;link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl&quot;],
  toolbar_mode: &quot;sliding&quot;,
  contextmenu: &quot;link image table&quot;,
  quickbars_selection_toolbar: &quot;bold italic | quicklink h2 h3 blockquote quickimage quicktable&quot;,
  plugins: &quot;preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion&quot;,
  promotion: false,
  autosave_ask_before_unload: true,
  autosave_interval: &quot;30s&quot;,
  autosave_prefix: &quot;tinymce-autosave-{path}{query}-{id}-&quot;,
  autosave_restore_when_empty: true,
  autosave_retention: &quot;30m&quot;,
  image_caption: true,
  image_advtab: true,
  image_class_list: [{&quot;title&quot;:&quot;None&quot;,&quot;value&quot;:&quot;&quot;},{&quot;title&quot;:&quot;Drop shadow&quot;,&quot;value&quot;:&quot;shadow&quot;}]
}" data-id="34920" data-fields="<div class=&quot;page-section&quot;>  <p></p>  <section>    <fieldset>      <legend> Page Section </legend>      <input autocomplete=&quot;off&quot; type=&quot;hidden&quot; value=&quot;false&quot; name=&quot;menu_item[page_sections_attributes][34920][_destroy]&quot; id=&quot;menu_item_page_sections_attributes_34920__destroy&quot; />      <div class=&quot;cms-admin-field&quot;>        <label for=&quot;menu_item_page_sections_attributes_34920_content&quot;>Content</label>:        <textarea class=&quot;tinymce&quot; name=&quot;menu_item[page_sections_attributes][34920][content]&quot; id=&quot;menu_item_page_sections_attributes_34920_content&quot;></textarea>      </div>      <script>//<![CDATA[TinyMCERails.initialize('try', {  });//]]></script>      <div class=&quot;cms-admin-field&quot;>        <label for=&quot;menu_item_page_sections_attributes_34920_collapsed_header_text&quot;>Collapsed header text</label>:        <input editor=&quot;template classic type classic&quot; type=&quot;text&quot; value=&quot;&quot; name=&quot;menu_item[page_sections_attributes][34920][collapsed_header_text]&quot; id=&quot;menu_item_page_sections_attributes_34920_collapsed_header_text&quot; />      </div>      <div class=&quot;cms-admin-field&quot;>        <label for=&quot;menu_item_page_sections_attributes_34920_include_contact_form&quot;>Include contact form</label>:        <input name=&quot;menu_item[page_sections_attributes][34920][include_contact_form]&quot; type=&quot;hidden&quot; value=&quot;0&quot; autocomplete=&quot;off&quot; /><input type=&quot;checkbox&quot; value=&quot;1&quot; name=&quot;menu_item[page_sections_attributes][34920][include_contact_form]&quot; id=&quot;menu_item_page_sections_attributes_34920_include_contact_form&quot; />      </div>      <div class=&quot;cms-admin-field&quot;>        <label for=&quot;menu_item_page_sections_attributes_34920_collapsible&quot;>Collapsible</label>:        <input name=&quot;menu_item[page_sections_attributes][34920][collapsible]&quot; type=&quot;hidden&quot; value=&quot;0&quot; autocomplete=&quot;off&quot; /><input type=&quot;checkbox&quot; value=&quot;1&quot; name=&quot;menu_item[page_sections_attributes][34920][collapsible]&quot; id=&quot;menu_item_page_sections_attributes_34920_collapsible&quot; />      </div>      <div class=&quot;cms-admin-field&quot;>        <label for=&quot;menu_item_page_sections_attributes_34920_has_borders&quot;>Has borders</label>:        <input name=&quot;menu_item[page_sections_attributes][34920][has_borders]&quot; type=&quot;hidden&quot; value=&quot;0&quot; autocomplete=&quot;off&quot; /><input type=&quot;checkbox&quot; value=&quot;1&quot; name=&quot;menu_item[page_sections_attributes][34920][has_borders]&quot; id=&quot;menu_item_page_sections_attributes_34920_has_borders&quot; />      </div>      <div class=&quot;cms-admin-field&quot;>        <label for=&quot;menu_item_page_sections_attributes_34920_full_width&quot;>Full width</label>:        <input name=&quot;menu_item[page_sections_attributes][34920][full_width]&quot; type=&quot;hidden&quot; value=&quot;0&quot; autocomplete=&quot;off&quot; /><input type=&quot;checkbox&quot; value=&quot;1&quot; name=&quot;menu_item[page_sections_attributes][34920][full_width]&quot; id=&quot;menu_item_page_sections_attributes_34920_full_width&quot; />      </div>      <div>        <a class=&quot;remove_fields&quot; href=&quot;#&quot;>Remove</a>      </div>    </fieldset>  </section></div>" href="#">Add Section</a>

单击链接时摩擦的javascript代码如下

  handleClick(link, e) {
    // Stop the function from executing if a link or event were not passed into the function.
    if (!link || !e) return;
    // Prevent the browser from following the URL.
    e.preventDefault();
    //get the tinymce config data
    let config = link.dataset.tinymce;
    // Save a unique timestamp to ensure the key of the associated array is unique.
    let time = new Date().getTime();
    // Save the data id attribute into a variable. This corresponds to `new_object.object_id`.
    let linkId = link.dataset.id;
    // Create a new regular expression needed to find any instance of the `new_object.object_id` used in the fields data attribute if there's a value in `linkId`.
    let regexp = linkId ? new RegExp(linkId, "g") : null;
    // Replace all instances of the `new_object.object_id` with `time`, and save markup into a variable if there's a value in `regexp`.
    let newFields = regexp ? link.dataset.fields.replace(regexp, time) : null;
    // Add the new markup to the form if there are fields to add.
    newFields ? link.insertAdjacentHTML("beforebegin", newFields) : null;
    console.log(config);

//    tinymce.init(config);

    tinymce.init(
      {
        event_root: null,
        selector: ".tinymce",
        menubar: "file edit view insert format tools table help",
        toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
        toolbar_mode: "sliding",
        contextmenu: "link image table",
        quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
        plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
        promotion: false,
        autosave_ask_before_unload: true,
        autosave_interval: "30s",
        autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
        autosave_restore_when_empty: true,
        autosave_retention: "30m",
        image_caption: true,
        image_advtab: true,
        image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
      }
    );
  };

console.log(config);的调用似乎显示了如下所示的正确 struct

{
  event_root: null,
  selector: ".tinymce",
  menubar: "file edit view insert format tools table help",
  toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
  toolbar_mode: "sliding",
  contextmenu: "link image table",
  quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
  plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
  promotion: false,
  autosave_ask_before_unload: true,
  autosave_interval: "30s",
  autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
  autosave_restore_when_empty: true,
  autosave_retention: "30m",
  image_caption: true,
  image_advtab: true,
  image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}

如果我从控制台复制并粘贴此 struct ,并将其作为对tinymce.init的调用的参数,则调用将按预期完美地工作,但当我将参数替换为配置变量时,函数将不起作用.

我已经try 在帮助器中_json、html_safe和RAW方法

推荐答案

在这里你绝对需要使用to_json.data-tinymce是一个字符串,当您从dataset读取它时,它不会被转换为json.你必须要做到JSON.parse点:

<%
  config = {
    event_root: nil,
    selector: ".tinymce",
    menubar: "file edit view insert format tools table help",
    toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
    toolbar_mode: "sliding",
    contextmenu: "link image table",
    quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
    plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
    promotion: false,
    autosave_ask_before_unload: true,
    autosave_interval: "30s",
    autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
    autosave_restore_when_empty: true,
    autosave_retention: "30m",
    image_caption: true,
    image_advtab: true,
    image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
  }
%>

<a class="add_fields" data-tinymce="<%= config.to_json %>" href="#">Add Section</a>

<script charset="utf-8">
  var config = JSON.parse(document.querySelector(".add_fields").dataset.tinymce)
  console.log(config)
</script>

Javascript相关问答推荐

在Chart.js 4.4.2中移动到不同大小的容器时,图表不会调整大小

使用Astro和React的动态API

如何通过继承contentitable属性的元素捕捉keydown事件?

Flisk和JS错误:未捕获的Syntax错误:意外的令牌'<'

如何访问react路由v6加载器函数中的查询参数/搜索参数

容器如何更改默认插槽中子项的显示?

如何使用JavaScript用等效的功能性HTML替换标记URL格式?

vanillajs-datepicker未设置输入值,日期单击时未触发更改事件

提交表格后保留Web表格中的收件箱值?

fs. writeFile()vs fs.writeFile()vs fs.appendFile()

调用removeEvents不起作用

嵌套异步JavaScript(微任务和macrotask队列)

TypeScript索引签名模板限制

colored颜色 检测JS,平均图像 colored颜色 检测JS

使用Google API无法进行Web抓取

当使用';字母而不是与';var#39;一起使用时,访问窗口为什么返回未定义的?

如何使用TypeScrip设置唯一属性?

如何确保预订系统跨不同时区的日期时间处理一致?

如何在Java脚本中对列表中的特定元素进行排序?

使用API调用的VUE 3键盘输入同步问题