Embedding in more than one host

Hello!

I have a question that I’m hoping someone can help me answer.

I have recently begun embedding for more than one site on my instance (pixls.us and digikam.org).

I’m wondering if there’s a way to differentiate which host is being embedded in for styling? One site is white background and the other is dark. I’m trying to set a font color that works for both, but it’s… difficult. :slight_smile:

Is there some neat answer I’m missing for setting a CSS style rule that will match one and not the other?

Perhaps adding another parameter to DiscourseEmbed that we can specify, like a discourseEmbedClass that we can then attach to the iframe/embedded tag as a class, so we can target it with the embed CSS?

  DiscourseEmbed = { discourseUrl: 'http://discuss.pixls.us/',
                     discourseEmbedUrl: 'REPLACE_ME' };

I’m happy to create a PR if someone could maybe point me to the relevant places to get started hacking?

I was playing around with the embed stuff the other day. You’re interested in public/javascripts/embed.js, and adding an additional query parameter to queryParams based on DE.discourseEmbedClass, which you could then set in the embedded code.

2 Likes

Why don’t you just style the embedded iframe from your sites’ css?

It’s not possible to modify the iframe from the parent (particularly cross domain). Unless I’ve missed something?

1 Like

Yes that’s right. But I saw you mentioned about background color particularly. You can style the background color of the outer div of the iframe, which is part of your website not discourse. And your embedded iframe will get that background color. I did that on my site.

Edit: I read your OP too quickly, so it seems you are looking for change the font color of the iframe. I don’t know a easy way for that. But still you may try to change the iframe to some background color that fits both the site style and discourse font color, as a workaround.

At the moment, my idea is to attach the discourseEmbedClass idea as a class to the embedded <html> element (basically, <html class='SOME-CLASS-PARAM'>) so the CSS can target this element w/o hacking at the actual embed code.

2 Likes

Well, I’ve made some headway, but could use a pointer if anyone is up for a little help.

I can pass the param to the /javacripts/embed.js.

My problem now is getting it to the iframe. Trying to set the iframe <html> element during creation gets wiped out when iframe.src is set.

Checking the source, it looks like it gets generated from /layouts/embed.html.erb

I am not sure how to proceed in passing this value to the template to add as a class to the <html> element. :frowning:

Ok, created PR for this. Hopefully it works and gets merged!

https://github.com/discourse/discourse/pull/4850

I believe a better approach would be to:

  • Update the embeddable_host table to add a custom class attribute
  • Update the admin UI to allow input in that field
  • Update the embed erb template to show that custom value

I have security concerns otherwise with passing the value through on the client side.

It’s a lot more work but I feel strongly it’s the better way to solve this issue. If it’s outside your realm of experience, maybe someone from the community could jump in and help you out?

5 Likes

Sweet merciful goodness I think I have something working.

I have added the necessary column to :embeddable_hosts and updated the admin UI for inputting that field.
(I am not sure what the naming convention for this file should be, I went with 20170505_add_embed_class_name_to_embeddable_hosts.rb).

I just need to add the class_name to the embed erb template, but am not sure how to access it within the template. Any pointers?

Ideally I’d like to add it to the <html> tag of the embed as a class…

If anyone gets a chance to check this, that would be awesome. :slight_smile:

From 4f1c0b97eafd6b0351d27689f5fad544d935b3ca Mon Sep 17 00:00:00 2001
From: Pat David <patdavid@gmail.com>
Date: Fri, 5 May 2017 18:08:18 -0400
Subject: [PATCH] Add embed class name setup for embeddable hosts

---
 app/assets/javascripts/admin/components/embeddable-host.js.es6     | 2 +-
 .../javascripts/admin/templates/components/embeddable-host.hbs     | 4 ++++
 app/assets/javascripts/admin/templates/embedding.hbs               | 7 ++++---
 app/controllers/admin/embeddable_hosts_controller.rb               | 1 +
 app/models/embeddable_host.rb                                      | 1 +
 app/serializers/embeddable_host_serializer.rb                      | 2 +-
 config/locales/client.en.yml                                       | 1 +
 db/migrate/20170505_add_embed_class_name_to_embeddable_hosts.rb    | 5 +++++
 8 files changed, 18 insertions(+), 5 deletions(-)
 create mode 100644 db/migrate/20170505_add_embed_class_name_to_embeddable_hosts.rb

diff --git a/app/assets/javascripts/admin/components/embeddable-host.js.es6 b/app/assets/javascripts/admin/components/embeddable-host.js.es6
index 2a5d7c0..70c1ed2 100644
--- a/app/assets/javascripts/admin/components/embeddable-host.js.es6
+++ b/app/assets/javascripts/admin/components/embeddable-host.js.es6
@@ -30,7 +30,7 @@ export default Ember.Component.extend(bufferedProperty('host'), {
     save() {
       if (this.get('cantSave')) { return; }
 
-      const props = this.get('buffered').getProperties('host', 'path_whitelist');
+      const props = this.get('buffered').getProperties('host', 'path_whitelist', 'class_name');
       props.category_id = this.get('categoryId');
 
       const host = this.get('host');
diff --git a/app/assets/javascripts/admin/templates/components/embeddable-host.hbs b/app/assets/javascripts/admin/templates/components/embeddable-host.hbs
index 5f25811..f4367ab 100644
--- a/app/assets/javascripts/admin/templates/components/embeddable-host.hbs
+++ b/app/assets/javascripts/admin/templates/components/embeddable-host.hbs
@@ -2,6 +2,9 @@
   <td>
     {{input value=buffered.host placeholder="example.com" enter="save" class="host-name"}}
   </td>
+	<td>
+    {{input value=buffered.class_name placeholder="class" enter="save" class="class-name"}}
+	</td>
   <td>
     {{input value=buffered.path_whitelist placeholder="/blog/.*" enter="save" class="path-whitelist"}}
   </td>
@@ -14,6 +17,7 @@
   </td>
 {{else}}
   <td>{{host.host}}</td>
+  <td>{{host.class_name}}</td>
   <td>{{host.path_whitelist}}</td>
   <td>{{category-badge host.category}}</td>
   <td>
diff --git a/app/assets/javascripts/admin/templates/embedding.hbs b/app/assets/javascripts/admin/templates/embedding.hbs
index 5db5cb6..bddcd76 100644
--- a/app/assets/javascripts/admin/templates/embedding.hbs
+++ b/app/assets/javascripts/admin/templates/embedding.hbs
@@ -2,9 +2,10 @@
   {{#if embedding.embeddable_hosts}}
     <table class='embedding'>
       <tr>
-        <th style='width: 30%'>{{i18n "admin.embedding.host"}}</th>
-        <th style='width: 30%'>{{i18n "admin.embedding.path_whitelist"}}</th>
-        <th style='width: 30%'>{{i18n "admin.embedding.category"}}</th>
+        <th style='width: 25%'>{{i18n "admin.embedding.host"}}</th>
+        <th style='width: 15%'>{{i18n "admin.embedding.class_name"}}</th>
+        <th style='width: 25%'>{{i18n "admin.embedding.path_whitelist"}}</th>
+        <th style='width: 25%'>{{i18n "admin.embedding.category"}}</th>
         <th style='width: 10%'>&nbsp;</th>
       </tr>
       {{#each embedding.embeddable_hosts as |host|}}
diff --git a/app/controllers/admin/embeddable_hosts_controller.rb b/app/controllers/admin/embeddable_hosts_controller.rb
index 7f15c9f..60d24a3 100644
--- a/app/controllers/admin/embeddable_hosts_controller.rb
+++ b/app/controllers/admin/embeddable_hosts_controller.rb
@@ -22,6 +22,7 @@ class Admin::EmbeddableHostsController < Admin::AdminController
     def save_host(host)
       host.host = params[:embeddable_host][:host]
       host.path_whitelist = params[:embeddable_host][:path_whitelist]
+      host.class_name =  params[:embeddable_host][:class_name]
       host.category_id = params[:embeddable_host][:category_id]
       host.category_id = SiteSetting.uncategorized_category_id if host.category_id.blank?
 
diff --git a/app/models/embeddable_host.rb b/app/models/embeddable_host.rb
index 1bcd29a..e87623a 100644
--- a/app/models/embeddable_host.rb
+++ b/app/models/embeddable_host.rb
@@ -57,4 +57,5 @@ end
 #  created_at     :datetime
 #  updated_at     :datetime
 #  path_whitelist :string
+#  class_name	  :string
 #
diff --git a/app/serializers/embeddable_host_serializer.rb b/app/serializers/embeddable_host_serializer.rb
index 61cf16e..e99ce6d 100644
--- a/app/serializers/embeddable_host_serializer.rb
+++ b/app/serializers/embeddable_host_serializer.rb
@@ -1,6 +1,6 @@
 class EmbeddableHostSerializer < ApplicationSerializer
 
-  TO_SERIALIZE = [:id, :host, :path_whitelist, :category_id]
+  TO_SERIALIZE = [:id, :host, :path_whitelist, :class_name, :category_id]
 
   attributes *TO_SERIALIZE
 
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 0d2c312..9e1a617 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -3454,6 +3454,7 @@ en:
         sample: "Use the following HTML code into your site to create and embed discourse topics. Replace <b>REPLACE_ME</b> with the canonical URL of the page you are embedding it on."
         title: "Embedding"
         host: "Allowed Hosts"
+        class_name: "Class Name"
         path_whitelist: "Path Whitelist"
         edit: "edit"
         category: "Post to Category"
diff --git a/db/migrate/20170505_add_embed_class_name_to_embeddable_hosts.rb b/db/migrate/20170505_add_embed_class_name_to_embeddable_hosts.rb
new file mode 100644
index 0000000..a2f6c5e
--- /dev/null
+++ b/db/migrate/20170505_add_embed_class_name_to_embeddable_hosts.rb
@@ -0,0 +1,5 @@
+class AddEmbedClassNameToEmbeddableHosts < ActiveRecord::Migration
+  def change
+    add_column :embeddable_hosts, :class_name, :string
+  end
+end
-- 
2.7.4

With the help of @darix we’ve got a PR that works on my tests here using the embeddable_hosts model (per @eviltrout).

https://github.com/discourse/discourse/pull/4857

Just an update and a request, if anyone might be able to help.

The patch works and merges fine, but @eviltrout wanted me to add a controller spec that checks for class_name in the record being viewed, and assigns the embeddable_css_class variable for embedding in the template.

I am not having any luck getting it to work despite a great pointer to exactly where I should be looking:

https://github.com/discourse/discourse/pull/4857#issuecomment-300542902

I have modified spec/controllers/embed_controller_spec.rb down in the context "with multiple hosts" so the last call to Fabricator should include a class_name:

...
Fabricate(:embeddable_host, host: 'https://example.com', class_name: 'example')

Following @eviltrout’s guidance, I then added a new test to check, but this is not working. :frowning:

    it "contains custom class name" do
      controller.request.stubs(:referer).returns("https://example.com/some-other-path")
      get :comments, embed_url: embed_url
      expect(assigns(:embeddable_css_class)).to eq('example')
    end

I’m apologize if I’m a little dense, but I could really use a hand here figuring out how to get this last bit working.

What is the test failure you’re seeing?

I was just going to answer you with a paste of the failure log, and it’s working. :confused:

So, it’s working. :tada:

Thank you very much for all the help (and patience)!

3 Likes