Custom image class rendering method - silverstripe

I wish to change img tag inside some Page template element to another tag. It's necessary to use parallax effect for each image on page (without specific class or created in CMS). Because Images cannot be styled, I decided to replace img tag with another. I can do this using JS, so poor browser won't be affected, but decided to ask could it be done by PHP and silverstripe?
In response to Conny Nyman's text. There an example JS code.
var el = document.querySelectorAll('.Paralax'); // Obtain images to which should been paralax effect apply
for (i = 0; i < el.length; ++i) {
// Create more elements, for example parent of div created bellow, so browser will properly calculates height - or use getComputedElementStyle from image element and apply result to nel
var nel = document.createElement('div');
nel.style.background = 'url("' + el[i].getAttribute('src') + '")';
el[i].parentNode.insertBefore(nel, el[i]);
el[i].parentNode.removeChild(el[i]);
}
Above code will do this, by using JS. I realize I need to not use JS, but add server support. Because Page was generated by many templates and I need allow to add paralax image from CMS, I need a way to add global template for all img tag, which checks only img have Paralax class.

Related

Moving the contents of a div to the bottom of code

On the website I am currently working on I have a div that loads slowly causing the page to load slowly but also jump as not all the positions elements load until after this slow div does. I cannot control the contents of this div as the content from the div comes from an external source.
So I was wondering if I could move the contents of this div to the bottom of my code so that it loads after the rest of my page whilst still keeping the position of the content on the same place on the webpage? Similar to what people do with some java script code.
Like Sergey said do something like this
javascript in the head
window.onLoad = function() { switchDivs(); }
HTML above where you want the content
<div id="whereYouWantIt"></div>
More HTML for the rest of your page
<div id="contentIsInHere"></div>
javascript here for function that switches the content around. Optionally call an external script here that contains this function.
<script>
function switchDivs() {
document.getElementById("whereYouWantIt").innerHTML = document.getElementById("contentIsInHere").innerHTML;
document.getElementById("contentIsInHere").innerHTML = "";
document.getElementById("whereYouWantIt").style.display = "inline";
}
</script>
</body>
CSS
#whereYouWantIt {
display:none;
other styles ...
}
#contentIsInHere {
display:none;
no other styles needed
}
You can use CSS to position the div and have it in the end. Or javascript is actually is good idea, load the content in a window.onload() function.
You can locate 2 divs - one where it should be and second in the bottom of page. Both of elements should have initially display none. After page will be loaded copy inner content of "pseudo" div by using JavaScript to the div you needed and make display block for this.

Alternatives to iframe srcdoc?

Generally I am against the use of iframes, but it solved a particular problem of mine.
The thing is that I have a tinyMCE-editor at a webpage. After the user have made the content using this editor the content is sent as HTML to a web application. This content is then displayed in a div. Thing is that tinyMCE often add styles with position absolute and things that break with the rest of the web applicaiton.
When testing I found out that the new HTML 5 iframe srcdoc="<p>Some HTML</p>" and seamless="true" was perfect for my situation. It looked seamless and the contents style and my style was intact. Sadly I now see that the HTML5 srcdoc attribute is not yet supported by Android (http://w3schools.com/html5/tryit.asp?filename=tryhtml5_iframe_srcdoc yields different result in chrome and android browser).
So the question is: Is there any alternative to the iframe srcdoc which will preserve all style of the received content and contain it in a div?
You can write to the document of an iframe like this:
const html = '<body>foo</body>';
const iframeDocument = document.querySelector('iframe#foo').contentDocument;
const content = `<html>${html} </html>`;
iframeDocument.open('text/html', 'replace');
iframeDocument.write(content);
iframeDocument.close();
As suggested by eicto by comment, jquery could be used to fill an iframe at the ready-event. In order to adjust the height of the iframe to the height of the content some dirty hacks had to be applied, but the code I ended up using is more or less:
HTML
<!-- IMPORTANT! Do not add src or srcdoc -->
<!-- NOTICE! Add border:none to get a more "seamless" integration -->
<iframe style="border:none" scrolling="no" id="myIframe">
Iframes not supported on your device
</iframe>
JS
// Wait until iFrame is ready (body is then available)
$('#myIframe').ready(function() {
var externalHtml = '<p>Hello World!</p>';
// Find the body of the iframe and set its HTML
// Add a wrapping div for height hack
// Set min-width on wrapping div in order to get real height afterwords
$('#myIframe').contents().find('body')
.html('<div id="iframeContent" style="min-width:'+$('body').width()+'px">'
+externalHtml
+'</div>'
);
// Let the CSS load before getting height
setTimeout(function() {
// Set the height of the iframe to the height of the content
$('#myIframe').css('height',
$('#myIframe').contents()
.find('#iframeContent').height() + 'px'
);
},50);
});
Use the new Data URI Scheme.
Example:
var content = "<html></html>";document.getElementById("my_iframe_id").src = "data:text/html;charset=UTF-8," + content;

How to remove alt style from chart component in c#.net?

I have a stacked chart component (from the MS Chart Control Library) on a c#.net webform which I created by dragging the control onto the design surface. I then edited the source html (.aspx page) to give the element a css class and remove the style attribute that was there originally. This was so that I could control the style from the css file instead of using embedded styling. Here is the html:
<asp:Chart ID="Chart1" runat="server" DataSourceID="SqlDataSource1" CssClass="smallBarChart"
IsMapAreaAttributesEncoded="True">
In the site.css file, I have specified the following:
.smallBarChart
{
width: 350px;
height: 230px;
}
When I run the web-app, the html that is rendered for the chart component has an "alt style" attribute added in. Even though it has the correct class attribute it is using the information contained in the "style" attribute. Why is this "style" attribute being generated by .net??. I have taken all style attribute info out of the original aspx file.
I don't have any instructions to change the style in my code behind (.cs) file
<img id="Chart1" class="smallBarChart" src="/Charts/ChartImg.axd?i=chart_2c39400223fb4933bf5a99e05d6119d4_3.png&g=b5c73578558442d3b9e1dd54cc127f20" alt="" style="height:300px;width:300px;border-width:0px;">
I should emphasise that I need to control the style of the chart component from my site.css file so any suggestions around using inline styling are not an option for me. Inline styling (adding a style attribute to a html element) is bad practice in any case!!!
I don't know why ASP.NET is overriding your work, but try this in your CSS:
.smallBarChart
{
width: 350px !important;
height: 230px !important;
}
Good Luck!
Set your chart's dimensions (Width/Height) at design time:
<asp:Chart Height="Unit" Width="Unit" ID="Chart1" runat="server" DataSourceID="SqlDataSource1" CssClass="smallBarChart" IsMapAreaAttributesEncoded="True">
Im beginning to think the answer to this is that because the .net runtime generates the html necessary to build the chart at runtime and because it transforms "Chart1" from an element into an element so that the browser can understand it, it will insert its own style attributes at runtime (even if I remove this in the .aspx file, the properties window shows 300px x 300px by default).
This being the case, it seems pointless assign a cssClass to the control since any matched CSS rule will be overridden by the inline style that .net gives the element when the HTML is served up (which is always 300 x 300px in my case for some reason.
In other words, I can not specify the width and height of an asp.net control in a separate css file because asp.net will ALWAYS give it its own style attribute at runtime.
The reason I posted this question is that I want to define the size of what I call a "Small Bar Chart" in the web site's CSS file so that if I have 10, 15 or 20 of these small barcharts on a page, I can resize them all. I guess the way to do this in .net is to create a custom control that is the right size since it wont let you control its style from a CSS file.
I encountered a similar problem using .net chart control and Zurb foundation, and we want our image to scale in a responsive layout. Zurb does a great job of that but really needs no width or height set on the image.
Unfortunately with the width and height are set on the image tag via the style attribute. We found that scaling was only performed on the width of our charts but the height remained the same. So, without proportional scaling our charts could look a little squashed.
Our solution is to subclass the chart control, override the render method, get the base class to render html and then modify the html to remove styles. Doing this allowed the charts to scale themselves proportional to their container.
Here is our solution:
public class ChartWithNoDimensionsSpecified : Chart
{
//we override this because the child chart controls may throw an exception and we don't want that to take down our whole page!
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
try
{
//get the base control to render itself into our stringwriter
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter chartWriter = new System.Web.UI.HtmlTextWriter(stringWriter);
base.Render(chartWriter);
//get the html rendered and find the start and end of the style tag
//note we assume no spaces between the style attribute = and "
//we also assume the img tag is first and there are no tags before it with a style
string html = stringWriter.ToString();
int pos = html.IndexOf("style=\"",StringComparison.OrdinalIgnoreCase);
if (pos != -1)
{
int pos2 = html.IndexOf("\"", pos + 8);
//we only want this one style to be set in the tag itself.
string replaceStyleAttr = "border:0px;";
//write the image tag, excluding the existing styles but replaced with our own...
writer.Write(html.Substring(0, pos + 7) + replaceStyleAttr + html.Substring(pos2));
}
else //incase we could not find the style tag...
{
//write out the existing standard html. We could alternatively throw an error here.
writer.Write(html);
}
}
catch (Exception ex)
{
//if there is an error, write this output instead
writer.Write("<div title=\"The chart control could not be rendered. This may be related to configuration, permissions or IIS being confused about access to the temp chart images folder (exception: " + HttpUtility.HtmlAttributeEncode(ex.Message) + "). If the charts have otherwise worked ok, recycle the IIS app pool and stop/start the site\"><span style=\"color:#ff0000;\">Error</span> (hover for detail)</div>");
}
}
}
In our case the charts are generated grammatically in c# code, and so we don't use the asp.net designer. If you do, you may need to make some changes to this to use that in the designer.

ASP.NET Theme stylesheet rendering

When a page with theme is rendered, the stylesheets link tags in the given theme are rendered right before the closing head tag. Does anyone know of a way to change that? Is there a way that I could have those tags be placed right after the opening head tag?
I know it can be down with jquery by just selecting all the link tags and placing it right after the opening head tag, but is there a way to set it on the server end?
Clarification
Let us say I have a single css file (themed.css) in my theme. In that css file, I have a single style definition for a div tag with an id of test:
#test {background-color:red; color:white;}
Let us also say I have a second css file (standard.css) that is NOT in my theme, but it has another definition of the div tag with an id of test:
#test {background-color:yellow;}
I have my page to use the theme, and I have a handwritten link tag to use standard.css. When the page is executed, the link tag for standard.css is before themed.css. When that happens my div tag with id of test has a red background and white forecolor. If I want the themed.css to apply and then standard.css to overwrite the necessary properties (yellow background with white forecolor), I would want themed.css and THEN standard.css. I can't do that because ASP.NET places the theme files right before the closing head tag.
I don't want to have to know that my theme's css files are the nth link tag in my head tag and then manual change any index whenever i may add a new css file outside of my theme.
Thanks!
I did a little checking in Reflector, and found something you may find interesting. The framework calls the SetStyleSheet method of a PageTheme-derived object to inject link controls in the header. This code snippet shows the relevant logic:
int num = 0;
foreach (string str in this.LinkedStyleSheets)
{
HtmlLink child = new HtmlLink { Href = str };
child.Attributes["type"] = "text/css";
child.Attributes["rel"] = "stylesheet";
if (this._styleSheetTheme)
this.Page.Header.Controls.AddAt(num++, child);
else
this.Page.Header.Controls.Add(child);
}
Translation? StyleSheetThemes inject the style sheets at the beginning of the header tag, and Themes inject the style sheets at the end.
This is consistent with the intended difference between themes and stylesheet themes; that is, that a theme always wins when there is a conflict between the skin and the control settings. Sure, a style in a non-themed .CSS file using the !important attribute could still override a theme style, but the positioning of the CSS files within the head tag strategically facilitates override-ability stylesheet themes.
Note that you can have both a stylesheet theme and a regular theme. Naturally, leave to the stylesheet theme things you design to be override-able, and to the theme things that should not be overridden.
One final observation is that the method is internal and non-virtual, so interfering with these two options would take some kung-fu-MMA-mad-reflection skills, and is probably not in the best interest of stability or maintainability.
As soon as your head element has runat="server" you can rearrange the collection in Page_PreRender:
protected void Page_PreRender(object sender, EventArgs e)
{
ControlCollection container = this.Page.Header.Controls;
foreach (var control in container.OfType<System.Web.UI.HtmlControls.HtmlLink>().ToArray())
{
container.Remove(control);
container.AddAt(0, control);
}
}

How to style content of pages without adding css class to element?

I use CMS for client and client doesn't know CSS he use WYSIWYG editor to put content in pages. Client adds Paragraphs, images, images in paragraph (left or right floated), ordered and unordered list, Tables. Problems comes when he want to add images in paragraph (left or right floated). and without adding css class it's not possible. And i don't want to add <div> in content because WYSIWYG editor can't manage div and client works in WYSIWYG mode.
How to style content of pages without using css class?
You will need your user to add a CSS class/style attribute to the image somehow - without adding something to the image to tell it to float right or left it won't float right or left.
If your question is how the client can add the class without having to manually edit the HTML I reckon the only way is to dive into the WYSIWYG editor's javascript and write something a bit like this towards the end of the image-adding process:
var alignment = prompt("Type l to align the picture to the left, and r to align the picture to the right","l").strToLower();
if(alignment == 'r')
{
//line of code to add class "right" to the image tag
} else {
//line of code to add class "left" to the image tag
}
What the code to add the classes should depend on how the WYSIWYG editor works
You can try using element selectors or ID selectors to add styles to HTML elements without referencing CSS class in them.
Element selector would add border to all images on the page:
img { border:1px; }
ID selector would do the same only to image with ID 'image1':
img #image1 { border:1px; }
Still you will need to reference the stylesheet from your page.
There are lots of different ways you can make CSS Selectors that don't require CSS classes. For example, to make a rule that applies to all img tags inside p tags, you could write this:
p img { float: left; }
But how are you hoping to determine which images need to be right-aligned and which images need to be left aligned? Does that data exist in the document in any machine readable format?
A WYSWYG should have "align" property for an image (at least those I have seen). You can then use CSS attribute selector img [align=left] { float:left; } or img [align=right] {float:right;} This wont work on IE 6,7 though, you can use JavaScript to mimic this for those browsers.

Resources