CHUVASH.eu

CHunky Universe of Vigourous Astonishing SHarepoint :)

Tag Archives: html5

Publishing Visio drawings as SVG

svg-004

In my post yesterday I showed how to publish Visio files as html image maps. That was one of the alternatives. Today I’ll present how to use SVG to achieve the same goal: publish Visio diagrams in SharePoint without having the Enterprise license. There are some alternatives:

  1. Show Visio diagrams as pdf files on SharePoint Pages
  2. Embed Visio diagrams as html image maps – Read more in my previous blog post
  3. Embed Visio diagrams as svg pictures – This blog post.
  4. Link to Visio files that are opened using Visio Web Viewer in a new browser tab.

SVG

SVG stands for scalable vector graphic, it is a xml-based format for defining images. It is supported in all modern browsers. Because SVG can be part of a page markup, it can be easily embedded into SharePoint.

Visio

In Visio you can save a drawing as SVG. Thanks to my smart colleague: Dan Saeden. So the process of exporting and embedding a drawing is almost the same as for an image map. An improvement is that you don’t have to update the html markup and you don’t need to upload or base64-encode any pictures. It’s all in the markup (DOM). See some screenshots below.

Advantages and Disanvantages

Compared to image maps and other methods, we get following advantages:

  1. It is scalable (not pixelish) – you can show it in a small screen, and a big screen.
  2. Only markup is needed (xml), no need for uploading images
  3. No additional bandwidth is required for downloading images to the browser
  4. No need for updating html structure, easier to explain how to do it.

There are also some disanvantages:

  1. Complex SVG files increase the DOM complexity and it may affect the performance in browser
  2. No support for older browsers: In IE8 it won’t work

svg-000

How to

Use your drawing of choice:

svg-001

Save it as an SVG file:

svg-002

Add a Script Editor Web Part to a page and paste the content of the svg file (open it in a text editor):

svg-003

That’s it:

svg-005

Summary

Visio files can be exported to many different formats. SVG is a great modern html standard for graphics that acts as a part of the DOM. It still requires a manual process of exporting and putting it on a SharePoint page, but it is a good way to make it modern, fast and even responsive (with some additional css). Editors don’t need to adjust the markup, only copy it.

Tip: Use the weakest CSS selectors

I am reading Mobile HTML5 written by Estelle Weyle. It is an awesome recap and new knowledge about html, css and javascript. I want to highlight one of tips I got: Use the weakest CSS selectors (can be found on page 204).

We all know, that inline CSS and !important are evil. They have a higher level of specifity and override the standard cascade of the CSS rules. If you use !important, then it will be hard to override CSS rules when you really need it. After these two classic “evils” the evil number three is overqualifying of CSS selectors. You should really never add more classes or ids or elements than needed. Consider this:

.warning {
  background-color: red;
}

It is often enough, you don’t need those:

html .warning
div .warning
div.warning, div > .warning
body p#myP.blue strong.warning

SharePoint

In SharePoint sometimes we want override some OOB CSS rules. We have our own “namespace” to do that really simple. We have added a class to the html tag: “contoso-html”. Then it was really easy to update any OOB CSS rules, just copy the selector and add .contoso-html:

.contoso-html #s4-workspace { }

We also use less preprocessor and nest our selectors which has resulted that almost all of our selectors contain .contoso-html. Now back to the tip of that blog. This “namespace” made it harder to adjust CSS rules for special cases, like left navigation in the Search Center, we were forced to add more specific selectors, and selectors became bigger and bigger.

What I would recommend today is to skip the .contoso-html namespace in the CSS but keep it in the masterpage markup, use it wisely, meaning only if the original rule doesn’t work. Don’t nest too much in less files. Try always to find the weakest CSS selector. It is especially important in the SharePoint “markup djungle”.

fallback for html5 placeholders

Placeholders are very handy in html5, we don’t need to fool with input values. But in SharePoint and IE we must provide fallback for placeholders if we want use them in other browsers. Here is an jQuery extension to do that:

(function ($) {
  $.fn.extend({
    ensurePlaceholders: function () {
      var input = document.createElement('input');
      var placeholderSupported = ('placeholder' in input);
      if (placeholderSupported) {
        return;
      }
      function setHints(elem) {
        var $elem = $(elem);
        var value = $elem.val();
        if (value == "") {
          var placeholder = $elem.attr("placeholder");
          $elem.val(placeholder);
          $elem.addClass("empty-text");
        }
      }
      function removeHints(elem) {
        var $elem = $(elem);
        $elem.removeClass("empty-text");
        var value = $elem.val();
        var placeholder = $elem.attr("placeholder");
        if (value == placeholder) {
          $elem.val("");
        }
      }
      this.find("[placeholder]").each(function() {
        setHints(this);			
      });
      this.on("focus", "[placeholder]", function(e) {
        removeHints(this);
      });
      this.on("blur", "[placeholder]", function(e) {
        setHints(this);
      });
    }
  });
})(jQuery);

Then “ensure placeholders” by running this function on a wrapper element which contains fields with the placeholder attribute:

jQuery("#form-wrapper").ensurePlaceholders();

Or why not to ensure all placeholders:

jQuery(document).ready(function() {
  jQuery(document).ensurePlaceholders();
});

This only runs if placeholders are not supported. This code toggles the class “empty-text”. It’s just a visual hint for not to be confused, otherwise the users can not know which is just a hint and which is the real value.

.empty-text {
  color: grey;
}

Enable Save in IE9 mode

Wouldn’t it be nice to use html5 and css3 in SharePoint? No problems, there is actually v5 master out there, created by Kyle Schaefer. Or just use h5ml5 and css3 right away in your webparts and pages. But there is a big problem. It doesn’t work in IE9–. One of the issues (even listed by Kyle) is that “save” doesn’t work in modal dialogs where Rich Text Editor is used. Especialy it is for modal dialogs.

The problem is not IE9, neither html5 and css3. After some digging in javascript code which is shipped with SharePoint I found out that the problem is some legacy javascript code which is not supported by IE9 but in IE8– (and compatibility mode).

When we set IE9 mode in IE9 Dev Tools (F12) and go to Tasks list and try to create a task, we’ll get an error:

It is RTE_GetEditorIFrame from init.js:

function RTE_GetEditorIFrame(strBaseElementID)
{ULSopi:;
	var ifmEditor=null;
	var doc=document;
	if ((null !=doc.frames) && (doc.frames.length==0) && (doc.parentWindow.parent !=null))
	{
		doc=doc.parentWindow.parent.document;
	}
	if ((null !=doc.frames) && (doc.frames.length > 0))
	{
		var ifmContainer=doc.getElementById(RTE_GetEditorIFrameID(strBaseElementID));
		if (ifmContainer !=null)
		{
			ifmEditor=doc.frames(RTE_GetEditorIFrameID(strBaseElementID));
		}
	}
	return ifmEditor;
}

So it is document.frames(“…”), not the usual document.frames[“…”]. What is that VB-style about?

Okay, the reason why this error isn’t raised in other browsers is just because this weird code isn’t run (Try to set break point there in Chrome or Firefox). And that’s why you never see Rich Text Editor toolbar in EditForm.aspx in Chrome and Firefox. To prove this, try to remove the Rich Text Column in your list. Then you can use “Save” button again, with IE9 mode!

Now we know the reason. How can we solve it. To do so we must find out where javascript defines whether to run or not Rich Text Editor toolbar.

First RTE_GetEditorIframe is invoked by RTE_ConvertTextAreaToRichEdit which is invoked by an inline script directly from NewForm.aspx:

if (browseris.ie5up 
  && (browseris.win32 || browseris.win64bit) 
    && !IsAccessibilityFeatureEnabled()){
    RTE_ConvertTextAreaToRichEdit("ctl00_m_g_0a9abd43_19a2_461e_b46f_6a1ae22a7ff1_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_TextField"
      , true, false, "", "1044", null, true, null, null, null
        ,"Compatible", "\u002ft001",null,null,null,null);
    }
else{
  document.write(" <br /><span class=\"ms-formdescription\"><a href='javascript:HelpWindowKey(\"nsrichtext\")'>Klikk her for hjelp med å legge til grunnleggende HTML-formatering.</a></span> <br />");
};

So there it is where the fishy code is invoked. Okay how can we intervene here to enable Save button? All solutions are based on disabling the bad code which is used to “convert” textarea to RichEdit.

1. Solution number one override RTE_ConvertTextAreaToRichEdit, just in style:

function RTE_ConvertTextAreaToRichEdit() {};

2. Solution number two: override IsAccessibilityFeatureEnabled, or this one:

function SetIsAccessibilityFeatureEnabled(f)
{ULSA13:;
	if (f)
		document.cookie="WSS_AccessibilityFeature=true;path=/;";
	else
		document.cookie="WSS_AccessibilityFeature=false;path=/;";
	var hiddenAnchor=document.getElementById("HiddenAnchor");
	var event;
	if (browseris.ie)
		event={ "srcElement" : hiddenAnchor , "fakeEvent" : 1, "enableStatus" : f};
	else
		event={ "target" : hiddenAnchor , "fakeEvent" : 1, "enableStatus" : f};
	if (hiddenAnchor==null || hiddenAnchor.onclick==null)
		return;
	hiddenAnchor.onclick(event);	
}

So to fool Accessibility, just set your own cookie: document.cookie=”WSS_AccessibilityFeature=true;path=/;”. But: don’t do that. It is really bad idea. Many features will stop working.

3. Solution number three is to override browseris. browseris is a browser which holds the information about the browser, simple. Here is how it is defined in init.js:

function Browseris () {ULSA13:;
	var agt=navigator.userAgent.toLowerCase();
	this.osver=1.0;
	if (agt)
	{
		var stOSVer=agt.substring(agt.indexOf("windows ")+11);
		this.osver=parseFloat(stOSVer);
	}
	this.major=parseInt(navigator.appVersion);
	this.nav=((agt.indexOf('mozilla')!=-1)&&((agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible')==-1)));
	this.nav6=this.nav && (this.major==5);
	this.nav6up=this.nav && (this.major >=5);
	this.nav7up=false;
	if (this.nav6up)
	{
		var navIdx=agt.indexOf("netscape/");
		if (navIdx >=0 )
			this.nav7up=parseInt(agt.substring(navIdx+9)) >=7;
	}
	this.ie=(agt.indexOf("msie")!=-1);
	this.aol=this.ie && agt.indexOf(" aol ")!=-1;
	if (this.ie)
		{
		var stIEVer=agt.substring(agt.indexOf("msie ")+5);
		this.iever=parseInt(stIEVer);
		this.verIEFull=parseFloat(stIEVer);
		}
	else
		this.iever=0;
	this.ie4up=this.ie && (this.major >=4);
	this.ie5up=this.ie && (this.iever >=5);
	this.ie55up=this.ie && (this.verIEFull >=5.5);
	this.ie6up=this.ie && (this.iever >=6);
	this.ie7down=this.ie && (this.iever =7);
	this.ie8standard=this.ie && document.documentMode && (document.documentMode==8);
	this.winnt=((agt.indexOf("winnt")!=-1)||(agt.indexOf("windows nt")!=-1));
	this.win32=((this.major >=4) && (navigator.platform=="Win32")) ||
		(agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1);
	this.win64bit=(agt.indexOf("win64")!=-1);
		this.win=this.winnt || this.win32 || this.win64bit;
	this.mac=(agt.indexOf("mac")!=-1);
	this.w3c=this.nav6up;
	this.safari=(agt.indexOf("webkit")!=-1);
	this.safari125up=false;
	this.safari3up=false;
	if (this.safari && this.major >=5)
	{
		var navIdx=agt.indexOf("webkit/");
		if (navIdx >=0)
			this.safari125up=parseInt(agt.substring(navIdx+7)) >=125;
		var verIdx=agt.indexOf("version/");
		if (verIdx >=0)
	            this.safari3up=parseInt(agt.substring(verIdx+8)) >=3;
	}
	this.firefox=this.nav && (agt.indexOf("firefox") !=-1);
	this.firefox3up=false;
	this.firefox36up=false;
	if (this.firefox && this.major >=5)
	{
	    var ffVerIdx=agt.indexOf("firefox/");
	    if (ffVerIdx >=0)
	    {
		var firefoxVStr=agt.substring(ffVerIdx+8);
	        this.firefox3up=parseInt(firefoxVStr) >=3;
		this.firefox36up=parseFloat(firefoxVStr) >=3.6;
	    }
	}
}
var browseris=new Browseris();
var bis=browseris;

So to fool this, just set:

 var browseris = {};

But you have to do it after init.js, so wrap into ExecuteOrDelayUntilScriptLoaded:

ExecuteOrDelayUntilScriptLoaded(function() { 
  var browseris = {}; 
}, "init.js");

After that you can press Save button. You’ll lose the Rich Text Editor, but you’ll have the nice features from CSS3.

DISCLAIMER: It is just an exploration lab. There is no warranty that it will work across the whole site. Don’t ever do such things things at home!

css3 fixers

If you just want to use css3 in your design and still use team functionality, take a look on pie.htc, jQuery.corner or iecss3.

 

Update 2015-09-16 Other Related Issues

Recently me and my colleague had to fix this issue again in SharePoint 2010. What we found was failing select elements (Choice field or Lookup field) in forms. There are some js functions that do not run in other web browsers rather than in IE in IE9 mode. All fail because of the inability of getting custom html element attributes.


//This is an override of FilterChoice (in core.js)
//We override this line: var strOpts=ctrl.choices; -> var strOpts=ctrl.getAttribute("choices");
//The reason is that this does not work in IE9 mode
//Don't forget this workaround. It might lead to other problems
function FilterChoice_new(opt, ctrl, strVal, filterVal) {
   var i;
   var cOpt=0;
   var bSelected=false;
   var strHtml="";
   var strId=opt.id;
   var strName=opt.name;
   var strMatch="";
   var strMatchVal="";
   var strOpts=ctrl.getAttribute("choices"); //THIS ONE
   var rgopt=strOpts.split("|");
   var x=AbsLeft(ctrl);
   var y=AbsTop(ctrl)+ctrl.offsetHeight;
   var elmWorkspace=document.getElementById("s4-workspace");
   if(elmWorkspace)
                                y -=AbsTop(elmWorkspace);
   var strHidden=ctrl.optHid;
   var iMac=rgopt.length - 1;
   var iMatch=-1;
   var unlimitedLength=false;
   var strSelectedLower="";
   if (opt !=null && opt.selectedIndex >=0)
   {
      bSelected=true;
      strSelectedLower=opt.options[opt.selectedIndex].innerText;
   }
   for (i=0; i < rgopt.length; i=i+2)
   {
      var strOpt=rgopt[i];
      while (i < iMac - 1 && rgopt[i+1].length==0)
      {
         strOpt=strOpt+"|";
         i++;
         if (i < iMac - 1)
         {
                                      strOpt=strOpt+rgopt[i+1];
         }
         i++;
      }
      var strValue=rgopt[i+1];
      var strLowerOpt=strOpt.toLocaleLowerCase();
      var strLowerVal=strVal.toLocaleLowerCase();
      if (filterVal.length !=0)
                                   bSelected=true;
      if (strLowerOpt.indexOf(strLowerVal)==0)
      {
         var strLowerFilterVal=filterVal.toLocaleLowerCase();
         if ((strLowerFilterVal.length !=0) && (strLowerOpt.indexOf(strLowerFilterVal)==0) && (strMatch.length==0))
                                      bSelected=false;
         if (strLowerOpt.length > 20)
         {
                                      unlimitedLength=true;
         }
         if (!bSelected || strLowerOpt==strSelectedLower)
         {
            strHtml+="<option selected value=\""+strValue+"\">"+STSHtmlEncode(strOpt)+"</option>";
            bSelected=true;
            strMatch=strOpt;
            strMatchVal=strValue;
            iMatch=i;
         }
         else
         {
            strHtml+="<option value=\""+strValue+"\">"+STSHtmlEncode(strOpt)+"</option>";
         }
         cOpt++;
      }
   }
   var strHandler=" ondblclick=\"HandleOptDblClick()\" onkeydown=\"HandleOptKeyDown()\"";
   var strOptHtml="";
   if (unlimitedLength)
   {
      strOptHtml="<select tabIndex=\"-1\" ctrl=\""+ctrl.id+"\" name=\""+strName+"\" id=\""+strId+"\""+strHandler;
   }
   else
   {
      strOptHtml="<select class=\"ms-lookuptypeindropdown\" tabIndex=\"-1\" ctrl=\""+ctrl.id+"\" name=\""+strName+"\" id=\""+strId+"\""+strHandler;
   }
   if (cOpt==0)
   {
      strOptHtml+=" style=\"display:none;position:absolute;z-index:2;left:" + x 
        + "px;top:" + y + "px\" onfocusout=\"OptLoseFocus(this)\"></select>";
   }
   else
   {
      strOptHtml+=" style=\"position:absolute;z-index:2;left:"+x+"px;top:"+y+" size=\""
        +(cOpt <=8 ? cOpt : 8)+"\""+ (cOpt==1 ? "multiple=\"true\"" : "")
        + " onfocusout=\"OptLoseFocus(this)\">"+  strHtml + "</select>";
   }
   opt.outerHTML=strOptHtml;
   var hid=document.getElementById(strHidden);
   if (iMatch !=0 || rgopt[1] !="0" )
      hid.value=strMatchVal;
   else
      hid.value="0";
   if (iMatch !=0 || rgopt[1] !="0" )
      return strMatch;
   else return "";
}
function SetCtrlMatch_new(ctrl, opt) {
  //ctrl.getAttribute("optHid") instead of ctrl.optHid
  var hid=document.getElementById(ctrl.getAttribute("optHid"));
  hid.value=opt.options[opt.selectedIndex].value;
  if (hid.value !=0)
    ctrl.match=opt.options[opt.selectedIndex].innerText;
  else
    ctrl.match="";
}

function HandleOptDblClick_new() {
  var opt=event.srcElement;
  //opt.getAttribute("ctrl") instead of opt.ctrl
  var ctrl=document.getElementById(opt.getAttribute("ctrl"));
  _SetCtrlFromOpt(ctrl, opt);
  SetCtrlMatch(ctrl, opt);
  opt.style.display="none";
}

function _SetCtrlFromOpt_new(ctrl, opt) {
  var hidId = ctrl.getAttribute("optHid");
  if (!hidId) { return; }
  //ctrl.getAttribute("optHid") instead of ctrl.optHid
  var hid=document.getElementById(ctrl.getAttribute("optHid"));
  hid.value=opt.options[opt.selectedIndex].value;
  if (opt.options[opt.selectedIndex].value==0)
  {
    ctrl.value=opt.options[opt.selectedIndex].innerText;
    ctrl.match="";
  }
  else
  {
    ctrl.value=opt.options[opt.selectedIndex].innerText;
    ctrl.match=ctrl.value;
  }
}

function HandleOptKeyDown_new() {
  var opt=event.srcElement;
  //opt.getAttribute("ctrl") instead of opt.ctrl
  var ctrl=document.getElementById(opt.getAttribute("ctrl"));
  var key=event.keyCode;
  switch (key)
  {
  case 13:
  case 9:
    _SetCtrlFromOpt(ctrl, opt)
    event.returnValue=false;
    opt.style.display="none";
    return;
  default:
    break;
  }
  return;
}

ExecuteOrDelayUntilScriptLoaded(function() {
  FilterChoice = FilterChoice_new;
  SetCtrlMatch = SetCtrlMatch_new;
  HandleOptDblClick = HandleOptDblClick_new;
  _SetCtrlFromOpt = _SetCtrlFromOpt_new;
  HandleOptKeyDown = HandleOptKeyDown_new;
}, "core.js");


 

Knas på Swedbanks mobilsida

Försökte ladda mitt kontantkort idag via Swedbanks mobilsida. Det gick inte. Och det berodde inte på iPhone som jag först trodde. Orsaken var ett knasigt användande av ett html5-attribut i en annars html4-hemsida: input type=”number”:

Att skriva en nolla i telefonnumret var helt omöjligt trots att sidan spottade ut fel och krävde en nolla. Med lite handpåläggning gick det!

Tur att man bara kunde rader type=”number” och att sånt knasigt fel inte låg i code-behind. Testar man inte sin programvara på Swedbank?

Two interesting html5-in-sharepoint presentations

New types of inputs in html5

html5 provides more types of inputs than the classic submit and text and a few more. Here you can see an example on fiddle

master page for html5 and css3

A great work: v5.master. I am recommending to try it.

The problem are some javascript bugs in the IE 9 when you run IE mode 9 that are necessary to enable html5 and css3 support. You can’t “save” a list item:

The reason why it doesn’t work in IE, but in Chrome, Firefox, is that IE invokes some functionality that it doesn’t invoke in other browsers.

Next: Enable Save button in IE9

Discovering SharePoint

And having fun doing it

Bram de Jager talking Office 365, SharePoint and Azure

My view and thoughts on Productivity and more.

My programming life

and everything in between

SharePoint Development Lab by @avishnyakov

It is a good place to share some SharePoint stories and development practices.

SharePoint Dragons

Nikander & Margriet on SharePoint

RealActivity - Real-time and trustworthy

Blog site of founder, RealActivty - Paul J. Swider

Mai Omar Desouki - Avid SharePointer

Egyptian & Vodafoner - Senior SharePoint Consultant

Cameron Dwyer | Office 365, SharePoint, Outlook, OnePlace Solutions

Office 365, SharePoint, OnePlace Solutions & Life's Other Little Wonders

paul.tavares

Me and My doings!

Share SharePoint Points!!

By Mohit Vashishtha

Jimmy Janlén "Den Scrummande Konsulten"

Erfarenheter, synpunkter och raljerande om Scrum från Jimmy Janlén

SPJoel

SharePoint for everyone

SharePointRyan

Ryan Dennis is a SharePoint Solution Architect with a passion for SharePoint and PowerShell

SharePoint 2020

The Vision for a Future of Clarity

Aharoni in Unicode, ya mama

Treacle tarts for great justice

... And All That JS

JavaScript, Web Apps and SharePoint

blksthl

Mostly what I know about SharePoint - CommunicoCuspis