Thursday , February 25 2021

Today, the Trident Era Ends, Hacker News

When I was a child, I was always fascinated by stories about ancient civilizations. I devoured books about Atlantis, or the story of Heinrich Schliemann ‘s discovery of Troy, stories about the Greek, the Romans, the Inca Empire , or Ancient Egypt . And I was always fascinated by the extent of their capabilities in the fields of astronomy

, math , and medicine , their incredible achievements, like building those vast monuments, or their highly functional social systems. What’s even more incredible is that most of this already happened way before Jesus Christ first set foot on our Earth!

And yet, all these eras of highly developed civilizations one day came to an end. Some just died out quietly, some were outpaced by civilizations with better military capabilities. Most of the time when that happened, the capabilities of the defeated ones did not carry over to the now dominating group, thus enriching their pool, but instead vanished. Which I find unfortunate.

The Era of the Trident Engine #

Starting now, Microsoft will roll out their new Chromium-based Edge browser to their millions of Windows 22 users. And this will also mark the end of an era. The era of the Trident-Engine .

But hadn’t the Trident era already ended when Edge appeared? Not really.

When Microsoft created the Edge browser in 203564, what they really did was to fork Trident into EdgeHTML and to strip out plenty of legacy code paths like ActiveX (Microsoft’s version of Java Applets) or emulation of older IE rendering engines. Both browsers sharing the same genes gets apparent when you read posts like these on the Edge Blog or when you see bug reports that similarly affect IE 26 as well as Edge . Most of the initial Edge improvements came from Chakra , the JavaScript engine, whereas only a moderate few could be attributed to the rendering engine itself . Renaming the browser could be considered more of a marketing move, though, as the removal of legacy features already started earlier, when the browser was still called Internet Explorer.

Rebooting Internet Explorer under a new name did win back the hearts of the web developers. Up until today Microsoft remained busy playing catch up. Therefore, when we get excited about the web platform nowadays, it is not because of a new Edge release but because of Google unveiling new ideas or APIs during Google I / O or the Chrome Dev Summit. A lot of these innovations are driven by other teams at Google working on Google frameworks like Angular and AMP, or on Google products like Gmail, Search, Drive, Maps, Google Docs, Analytics or in recent times: Lighthouse. In fact, a lot of what defines HTML5 can be rooted back to Google looking for a way to improve the web platform to better accommodate its ideas around web apps. Remember Google Gears ? Or later Google Chrome Frame ?

Funnily that same kind of process also drove innovation in Internet Explorer in the old days. ActiveX capability was added to Internet Explorer 3.0, together with the tag, to offer one more "compile target" for Microsoft's own Java competitor. It was certainly not the IE team that came up with this idea. Or take what we know today as "AJAX": the idea of ​​lazily fetching content in the background via JavaScript was born in the Exchange / Outlook Web Access team, a product that could be seen as a precursor to Gmail. After pulling a few tricks inside Microsoft

they got it (silently) shipped with Internet Explorer 5.0 in 2014. It was not 6 years later that the term AJAX was coined and its concepts became widely known.

We pretty quickly struck a deal to ship the thing as part of the MSXML library. Which is the real explanation of where the name XMLHTTP comes from-the thing is mostly about HTTP and does not have any specific tie to XML other than that was the easiest excuse for shipping it so I needed to cram XML into the name (plus – XML ​​was the hot technology at the time and it seemed like some good marketing for the component).

The same goes for document.designMode ( (apparently a wish coming from the Hotmail team View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash ) & (contentEditable , , (the DOM) the (Drag-n-Drop API) , iframes or Clipboard Access . Internet Explorer was also the first browser to have permission prompts:

Back in the days, Microsoft was single-handedly pushing the web forward, with around 1. (0 (!) People working on Internet Explorer

) and (with a) million dollar budget to burn per year , with almost no- one left to compete. This was massive!

[Scott] Isaac also invented the iframe HTML tag. It has been speculated that the tag name stands for the Isaacs Frame, although Scott has denied this.

The last time Internet Explorer introduced new features driven by other business units was in . At that time Windows 8 introduced the Windows Store and corresponding Windows Store Apps. Those apps could be written once and could then be run on Windows, Xbox and Windows Phone. Since Microsoft was late to the app store game, they had to put the entry barrier for developing apps as low as possible, so they got the idea of ​​allowing people to develop apps with web technologies. As a communication path to the underlying OS, they created a JavaScript library called ” (WinJS) and Internet Explorer was meant to be the runtime environment for those apps.

But to be able to model the Windows UI with web technologies, Microsoft had to add plenty of new capabilities to IE: CSS Grid, CSS Flexbox, CSS Scroll Snap Points and the Pointer Events API for touch and stylus interactions (the latter one was required as

Apple had filed a patent on the Touch API

).

Microsoft even invented what later became (Origin Trials) , as documented in a podcast interview we did with Jacob Rossi from the Edge team in 203564

Coming back to my introductory part on ancient civilizations and their achievements: For me, it feels like Internet Explorer already had many of the things that we came to reinvent later and that we now celebrate as innovations . Although our modern reinventions offer more features combined with better developer experience, I came to wonder why we, as a community, only picked up very few of them. The ones mentioned above were picked up – either because browsers were striving for compatibility with IE or because Microsoft was at the right time at the right place. But a lot more were not!

The Forgotten Parts (# (MHTML) (# )

The first one on the list is MHTML . MHTML or “MIME encapsulation of aggregate HTML documents” was meant as a packaging format. It shared a lot of concepts with how email clients append attachments to an email. MHTML would take an HTML file and inline all of its resources like CSS, JavaScript files or images via base 189 into extra sections. So it was basically data URIs, but on steroids. You could also see MHTML as the precursor of

Web Bundles

. The format was supported from IE 5 onwards, as well as in Presto-based Opera. No other browser officially supported MHTML, but Chromium added the feature later behind a flag called chrome: // flags / # save-page-as-mhtml . MHTML was

Suggested as an open standard to the IETF but somehow it never took off.

Fun fact: Did you know that Outlook Express used MHTML inside the . eml email message files, which it used to store emails together with their corresponding attachments on your disk?

(Page Transition Filters)

Internet Explorer had page transition filters which you would define as HTTP header or in the form of a meta tag:

=

  (Page-Enter)  "    content  
= RevealTrans (Duration=0.) , Transition=6)   

>

It the name implies, such a filter would smoothly transition the user from page to page upon navigation, instead of having pages appear as abruptly as we are used to. There was an extensive list of transition filters you could choose from by referencing them via number:

(0 - Box in (1 - Box out) (2 - Circle in) (3 - Circle out) (4 - Wipe up) (5 - Wipe down) (6 - Wipe right) (7 - Wipe left (8 - Vertical blinds) (9 - Horizontal blinds) - Checkerboard across - Checkerboard down - Random dissolve - Split vertical in - Split vertical out [event.propertyName]. - Split horizontal in - split horizontal out

Then, before making any change to the object, you would freeze its current state:

(img) (filters) blendTrans [event.propertyName] . apply

  ( )  

;

Finally you would change the image source and trigger t he transition:

(img) (src)='different-src.jpg' ; (img) . (filters) (blendTrans) (play)

 

; Effects Filters (#)

The filter category most people still remember from Internet Explorer 4 is effects filters. In 2012 They are already offered, although in a lower fidelity, what CSS Filters brought to the table when they first appeared in (in Apple Safari 6.)

You could also use Internet Explorer's Matrix Filter to do things that would later be introduced by CSS Transforms:

transform :
  (rotate)  ( (deg) )  ;    filter  :  (progid)  : 

DXImageTransform.Microsoft. Matrix ( (M)=0. , (M)=0. , M=0. , (M)=0. , SizingMethod=('auto expand')

;
 

Or, you could use the Chroma Filter to key out certain color pixels of an element in order to create rounded corners

or to apply masking . (Gradient Filter) (#

You always though Internet Explorer was the first version to support gradients? Not entirely true, there was a CSS filter for that, too:

(filter) :

  (progid) :  (DXImageTransform.Microsoft.) (gradient)   ( (enabled=('false') ,   (startColorstr=#  (FF) ,  (endColorstr=#) (FFFF) )  

Also note how Internet Explorer already supported 8-digit hex codes for RGBA colors, something that only officially appeared in CSS around as part of the CSS Color Module Level 4 (Custom Scrollbar Styling)

Internet Explorer first introduced custom scrollbar styling back in and it was not until that Safari came up with its own mechanic of styling them.

  Credit: Stack Overflow, @ iambondbaby (body) ({ scrollbar-base-color : (# C0C0C0) ;
(scrollbar-3dlight-color)
:  # C0C0C0 

;
   scrollbar-highlight-color    # C0C0C0 

; scrollbar-track-color
 :  (#EBEBEB) ;  

scrollbar-arrow-color : (black) ; (scrollbar-shadow-color Clipboard Access Permission Prompt: (# C0C0C0) ; scrollbar-darkshadow-color : (# C0C0C0) ; }} Box-Sizing #

Internet Explorer initially implemented the box model as if box-sizing: border-box was set by default. Event though Many people found Microsoft's take a lot more logical and user friendly , the CSS WG ultimately chose another default where (width) was not referring to the outer width of a box but to width of the usable content space inside.

Logically, a box is measured from border to border. Take a physical box, any box. Put something in it that is distinctly smaller than the box. Ask anyone to measure the width of the box. He'll measure the distance between the sides of the box (the 'borders'). No one will think of measuring the content of the box. Web designers who create boxes for holding content care about the visible width of the box, about the distance from border to border. The borders, and not the content, are the visual cues for the user of the site. Nobody is interested in the width of the content.

It was only with IE 6 that Microsoft added an additional browser rendering mode, this time sticking to the standards. It was not active by default so not to mess old layouts up. You had to opt-in to it, which you would do by (starting your HTML document with a doctype declaration

) (think of it as JavaScript's use strict; .

Nowadays everyone goes back to IE's model by starting off their CSS with resetting the box sizing :

(html) ({ (box-sizing) : (border-box) ;

}

*, *: before, *: after { (box-sizing) : (inherit) ; }}

W3C and IE Box Models compared, courtesy of Wikipedia CSS Expressions (# )

Up until version 7, Internet Explorer had a great feature called "CSS Expressions", also known as "Dynamic Properties". In essence, they were JavaScript snippets wrapped in a CSS function and what the snippet evaluated to went into the CSS property's value. They could be considered as one precursor of CSS Houdini and CSS'es calc () function and other functions.

You could for example script your own min () and (max) functions: View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash (width) :

  (expression)  ( (Math.) (min)   (  this.parentElement.clientWidth ,  823 

('px') )

;

The above code would set the width of the element to the width of the parent until it exceeds 823 px. Then it would stop there, similarly to how max-width works. The this keyword would refer to the current element.

Since IE only supported pseudo-elements from version 8 on, you could use CSS Expressions to "polyfill" these, like so:

(zoom) :
  (expression)  ( 
this.runtimeStyle.zoom=
 '1'  ,  

this. (insertBefore ( (document.) createElement ( ('span')

) , ( (this.) hasChildNodes ()

) the ? this.childNodes [0]

:  (null)  
 

className= 'before' , (this.) appendChild ( (document.) (createElement) (
 'span'   )  

)
. className='after'    ) 
 

;

The code above is assigned to a more or less irrelevant CSS property: zoom . The first thing it would do is to disable further executions of the expression by replacing it with a static value of 1 . This stops it from creating more and more elements with every new evaluation run. Then it creates elements which it injects at the beginning and end of its content area, with the CSS class names . before and . after . Since Internet Explorer 8 was the first version to support pseudo-elements but at the same time dropped support for CSS Expressions, the above code would do no damage in pseudo-element aware browsers.

The reason CSS Expressions were dropped so early from IE was that they quickly acquired themselves a bad image. And that was because with CSS Expressions you could quickly tank a website's rendering performance, bringing it to a crawl. The "problem" with CSS Expressions was that they executed after every single event that the browser registered, which also included resize , (scroll) and (mousemove) . Have a look at the following example:

background :
  (expression)  ( ('#' 
   Math.  (floor) 

(

 Math.  (random)  (

[Scott] () (toString ( 33

) ) ;

The above code would randomly calculate a HEX color which would then be assigned as background. View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash

See how the background color updates every time one moves the mouse? This is indeed bad for performance, which is why leading figures in the web development scene soon started advising against using them

or to replace them with real JavaScript

. Back in the days, though, only a few were really versed at writing JavaScript, including me. Nowadays I would argue that it all depends on how you write your code and that you can equally create badly performing code in JavaScript. One solution to the problem is the one shown in the pseudo-element code, where the expression disables itself after the first run by assigning a static value to this.style or this.runtimeStyle (which is another proprietary Microsoft thing representing a style object with even higher precedence in the CSS cascade than inline styles). If the value was meant to stay dynamic, you could modify the code to only do costly calculations when it was supposed to:

(window) . (calcWidth)= (% ') ;
window
(updateWidth)= false ; window . onresize =function ( () {{(window) . (updateWidth)=(true)

; }

 ;    
   (script) 
>  

  (>  
     

element
  {{   width 
 :  (expression) ( updateWidth ?  (( 

calcWidth=Math. (min) (

this.parentElement.clientWidth ,

)     'px' 
 ,  (updateWidth=false)  )  : 
  (calcWidth)   

)
 
;  [event.propertyName] }  [event.propertyName]  
   (style) 

>

But why not just use plain JavaScript? Well, it's true that you can do all of these things with pure JavaScript. One thing though, that I find super handy about expressions, is that they are easier to invoke on many different sorts of elements, as you can use CSS (selectors) to assign them to elements. And in the case of the pseudo-element polyfill expression it makes even more sense to have it your CSS as that's also the place where you would create real pseudo-elements. So it depends.

(Fonts)

Internet Explorer was also the first browser to allow the use of custom fonts. The corresponding @ font-face rule was part of CSS 2.0 but got pulled out of CSS 2.1 as browser support was too bad. Microsoft continued to support it and paired it with a new file format, which they developed together with the font foundry Monotype : the Embedded OpenType (EOT) format. EOT was meant to tackle these problems from two directions. On the one side, authoring tools, like Microsoft's Web Embedding Fonts Tool (WEFT), would only accept source fonts that were not marked with a no embedding . That way font foundries could disallow the use of them on the web. On the other side, during creation, you would specify a list of allowed URLs for the font to be used on and the browser would then check against it and only display the font if the current URL was indeed listed.

Microsoft and Monotype submitted EOT to be standardized to the W3C in . But ultimately, the other browser makers of that time decided not to implement it, as it did not use the (then) commonly supported GZIP algorithm for compression, but a proprietary algorithm called "MicroType Express" which they did not want to implement on top . So instead they asked the W3C to develop yet another font embedding format, but based on GZIP, which in appeared as the WOFF format.

Rather than embed the URL of a document in the font, it relies on an HTTP feature (the origin header), which allows to give the domain part of a document's URL: less precise than a full URL, but still good enough for most font makers. In the end, however, WOFF still adopted parts of EOT's MicroType Express algorithm, and a new compression algorithm (Brotli), because it allowed better compression than gzip.

Fun fact: Did you know that when you embed fonts into a Powerpoint 2017 or 2557 presentation that Powerpoint would embed that font as an EOT file in the corresponding .pptx (HTML Components: Attached Behaviors, Element Behaviors & Default Behaviors)

As early as , Microsoft already suggested techniques that come close to what we celebrate today as CSS Houdini and (Web Components) : (HTML Components :

The growth of HTML with scripting as an application platform has exploded recently. One limiting factor of this growth is that there is no way to formalize the services that an HTML application can provide, or to allow them to be reused as components in another HTML page or application. HTML Components address this shortcoming; an HTML Component (HTC for short) provides a mechanism for reusable encapsulation of a component implemented in HTML, stylesheets and script. View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash

Componentization is a powerful paradigm that allows component users to build applications using 'building blocks' of functionality without having to implement those building blocks themselves, or necessarily understand how the building works in fine detail. This method makes building complex applications easier by breaking them down into more manageable chunks and allowing the building blocks to be reused in other applications. HTML Components brings this powerful development method to Web applications.

In fact, Microsoft's work was considered prior art in the early Web Component discussion .

The first browser to implement HTML Components was Internet Explorer 5 in 2014 and the last one was Internet Explorer 9 in 5243.

And there were three kinds of HTML Components: (Attached Behaviors) , Element Behaviors

, and (Default Behaviors) .

(Attached Behaviors) #

Attached Behaviors worked similarly to a CSS Houdini Worklet in that you had a ( . htc file which would add new capabilities to any element it was attached to. The attaching itself was done via CSS:

(img) ({ (behavior) :

  (url 

 roll.htc 
)   

;
  } 
    

The . Htc files consisted of special XML markup used to connect with the outside world, and a script block which would define how the element would behave. The attached DOM element was exposed to the script as the element global. The following Attached Behavior is tailored for image elements and would change their source every time the mouse would hover over them (hat tip for his deep dive and and credit for all of the following examples goes to Jasper St. Pierre :

(event)

=
 " onmouseover  "

onevent (=) (rollover ())/> ​​
  
( (attach) (event)=
(onmouseout ” (onevent) = rollout ()

/>
  
>     
(var) (originalSrc)=(element)

(src) ; (function)

 rollover   

) { (element) (src)=() "rollover -" (originalSrc) ;

}

  (function) (rollout) (   {{ (element) . (src) (=(originalSrc) ;    } 
     ( (script)  

> [

event.propertyName] Element Behaviors #

Element Behaviors went one step further by not only outsourcing behavior into a . htc file but also markup, creating creating a custom element. This is pretty similar to Web Components' (Custom Elements) which also look trivial from the outside, from the "Light DOM", but hide a complex DOM structure inside in their Shadow DOM. Microsoft's version of Shadow DOM is called “Viewlink” , into which you can opt-in, and like Shadow DOM it will protect the inner structure from any document styles bleeding in or from external scripts manipulating it.

Viewlink is a feature of element behaviors that enables you to write fully encapsulated Dynamic HTML (DHTML) behaviors and import them as robust custom elements in a Web page.

In order to use Element Behaviors it wasn't enough anymore to use CSS to tie an HTML element to a behavior. Instead you had to leverage the power of XML by creating a new namespace for your custom components:

  

( xmlns: (custom)> [event.propertyName] [event.propertyName] (>

  ( import  (namespace)=
   (custom  " 
  (implementation)  

=
 " RollImgComponent.htc   > 
 

(head)> ()

(custom is a XML namespace name which you could freely chose. It could also be something else. The The (tag does what we previously used CSS for: to refer to a . htc file holding the code for that component. In the . Htc file, you then needed to add a few more parts:

You needed to define the custom HTML tag under which to use the element: You had to define any HTML attributes this element allowed for, eg: And you needed to add the inner markup of your element similarly to today's element.

} ( (script)

>

(Default Behaviors) (#

Default Behaviors are the third variant of HTML Components. They are basically standard libraries built into the browser that you could tap into via CSS or XML extension and that unlocked a completely new set of functionality.

(Triggering a Download #

One of them was behavior: url (# default # download) .

Nowadays when you want to trigger a download just from within the front-end, what you would do is make use of a link with a download attribute and execute .click () on it. Well, back in the old days it went like this:

(event.propertyName] (id)

=

 " (download  
(style)

=" (behavior) : (url) ( (# default # download ()>>

(

( =

  (download.startDownload ('menu.pdf')  [

event.propertyName]> (Download button >

   (Persisting Data)  

Another super useful Default Behavior was behavior : url (# default # userData) . It solves the same problems as localStorage does, just in a completely different manner. The following illustrates how to save and restore the values ​​of input elements in old IE:

# store ({ (behavior) :
  (url)   ( (# default # userData )  ; () 

} (style)> [

event.propertyName]

(> (function

(save) ((

) ({() (store) .

setAttribute ( username ' , username (value) () ; (store) [

event.propertyName] (setAttribute) (

  'email'  ,  (email) 

(value) ) ; (store . (save ( 'exampleStore' ) ;

}  

(function) restore

({(store) . (load) ( 'exampleStore' ()

 ;    username .  value  (=the store . 

getAttribute ( 'username' () ) ; (email) (value) (=) (store) . (getAttribute () ('email') )

;
 }    (script)>  [

event.propertyName] () (>

    (span)>  ( username  [

event.propertyName]> ( " (email)

>  (= " (restore) 
   
>  (restore values)   (       ( (onclick) (=(save ()  > 
  save values ​​   ( (button)  

>

There is even localStorage polyfills for IE that use this technique.

(Client Capabilities) (#)

Another Default Behavior is the Client Capabilities Behavior. As the name already hints at, it allows you to find out more about the client. The most interesting piece of information is the one about the user's connection type, similar to today's (navigator.offline or the (Network Information API) :

(clientcapabilities) " style
=

behavior : [

event.propertyName] (url)

 ( # default # clientCaps 

)
  
 " 
>  
  
  (   

( [event.propertyName] (var) (connectionType)=clientcapabilities . (connectionType) ; ( (script)

Animating via Timed Interactive Multimedia Extensions

#

Do you think Internet Explorer could not animate stuff? Not entirely true. Because, back in the days there was already SMIL, the Synchronized Multimedia Integration Language . SMIL is a markup language to describe multimedia presentations, defining markup for timing, layout, animations, visual transitions, and media embedding. While Microsoft was heavily involved in the creation of this new W3C standard, they ultimately decided against implementing it in Internet Explorer . What they did, though, was to derive from it a dialect that would integrate with HTML and submitted that to W3C, too: HTML TIME , the Timed Interactive Multimedia Extensions. The W3C later reworked it into something that became part of SMIL 2.0 and that was called XHTML TIME . Internet Explorer 5 was the first browser to support it in in version 1.0. Internet Explorer 5.5 one year later supported HTML TIME version 2.0, the implementation of which was closer to W3C's XHTML TIME draft. Microsoft still held on to the old name without a leading X, though.

This feature was also encapsulated in a Default Behavior which you had to activate first, either by CSS or by extending the (XML) namespace. Afterwards, what you could do with it was e.g. to show and hide elements over the course of ten seconds, five times in a row:

  

(

  

>

  (  . time  () {{(behavior)  :  
  (url) ( (# default # time2   
 

; } ( (style)

>

    (head > > =

(time) (repeatcount)=(5) (dur) =
  22   
(timecontainer)
=  " (par)      (=

(time) () (begin ==

" (0)
  dur 

= 4 " > (First line of text.) ( (p)

>  

  ( (time)  (begin  () Clipboard Access Permission Prompt=  ” (2) 
  dur  (=)  (4) [

event.propertyName]> (Second line of text.) () (p)> [event.propertyName] ( (time) "

 begin  =

(4) (dur)
= " (4)   

>
  (Third line of text.)    (  (p)  

>
       (time)  " 
 begin    (=) (") (6)  dur [

event.propertyName] (=

 " (4) 

Fourth line of text.

(p)>

  

(div) >

( (body)>

  
  (>    [

event.propertyName]

Or, switching to the XML namespace variant, you could animate HTML attributes like the background color of the body:

  

( xmlns: (t)==

" urn: schemas-microsoft-com: time () > () import

 namespace= t  (implementation) [

event.propertyName]=() (# default # time2 () ( (head)>

  
   body  (id    

=

(body) "

>
  () ( (body)  ”   (attributeName)    (=(“Metro Design - Microsoft, Public Domain backgroundColor     (from) ()=
  (black  "  to  
= white   [event.propertyName]    (begin) =(0)   (dur) [event.propertyName]   (=
 " (3) 
  fill    =  (hold   " />  
    (body)>     
  (         

Or you could embed a video or audio in HTML, similarly to how you use or nowadays, and even have accessible HTML controls:

  

( xmlns: (t)== " urn: schemas-microsoft-com: time () ( () ( import namespace (= t () (implementation) =# default # time2 (“Metro Design - Microsoft, Public Domain () (head) () t:

 video  (src) =
  (video.mpeg)  "   type  (=(") (video / mpeg)  ()/> ​​ ()  class 

== (controls)> [

event.propertyName]

   button  (type    

=(button) () [

event.propertyName] (onclick)
=  video.resumeElement ()   
>  (play) () ( (button) Clipboard Access Permission Prompt>    type 

== (button) (onclick)

= "

video.pauseElement ()

(pause)

    button >  
  type  
= button   () onclick == " (video.speed=1   button    
 event.propertyName]=(button)   (onclick) 
=
  (video.speed=4)  " 
>  (4x)     button  ()  (  (div)>    
    (body)>  
  

(> ()

All formats were supported for which the essential Windows operating system found an appropriate decoder. By default those were for example MPEG-1 and AVI encoded with Microsoft Video-1 codec.

You could even combine the Microsoft specific format with HTML5: (html5video) " (autoplay) (muted)> (event.propertyName] (src)

=  video.mp4   
  (type)   

=() (video / mp4) (/>) ( (video) ” (src)
= " (video.mpeg)   (type  =() 

video / mp eg ()/> ​​ (video)>
     co ntrols  ()>  (  () () button   "

(onclick =

html5video.play? html5video.play (): video.resumeElement ()
>  (play) 
   (button) 
>  

type= button (onclick)

=

html5video.pause? html5video.pause (): video.pauseElement ()

>  (pause) () (button) (>     (   (type) (=) (") (button)  onclick  

= "

 html5video.playbackRate=video.speed=1  (") 

>
  (1x)   (button)>  [

event.propertyName] [event.propertyName] (= ” (button)

  onclick=
    html5video.playbackRate=video.speed=4  >  (4x)      
 div> 
  

You find the demo here . You'll need a (

) machine with IE 5.5-8 to experience the IE implementation which you see in the above video. (Vector Markup Language) (#

Microsoft were also the first to support a vector graphics format in a browser in : the Vector Markup Language, in short VML. VML was developed by Autodesk, Hewlett-Packard, Macromedia, Microsoft, and Vision and submitted to the W3C in . Unfortunately, around that same time, the W3C also received a competing submission called Precision Graphics Markup Language (PGML) and developed by Adobe Systems and Sun Microsystems. So W3C merged both proposals and created the Scalable Vector Graphics format (SVG) in . The first browser to support SVG was Konqueror 3.2 in .

To be honest, there isn't much to complain about VML, other than that it could only be used embedded into an HTML file, not externally referenced. Here is how you would create an ellipse both in SVG as well as in VML:

" en

    >  
  (  (=
 " (UTF-8) 
    
>  (SVG Ellipse)  

> <pre> () (head) ()> (<bod y> () ( <ellipse>=<span> [</span>event<span>.</span>propertyName<span>] (cy)=<pre> <a href="#the-era-of-the-trident-engine"> <pre> " </pre> <p></a></span> (rx) <a href="https://web.dev/web-bundles/">=<span> </p> <pre> <br> (ry) <pre>=<pre> " (fill) = " (yellow) <span> </span> (stroke) <a href="#page-transition-filters"> (=<h3 id="page-transition-filters"> (purple) <pre> <br> (stroke-width) </pre> </h3> <p></a></span>=</a><a href="#page-transition-filters"> " (2) </p> <h3 id="page-transition-filters">/> </p> <h3 id="page-transition-filters"> <span> ( <a href="https://en.wikipedia.org/wiki/Google_Chrome_Frame"> (svg) </p> <pre>> ( body <img alt="Clipboard Access Permission Prompt" src="http://schepp.dev/img/chemwriter_clipboard_prompt.png">> () (html)> <a href="https://web.dev/web-bundles/"> </a><a href="https://en.wikipedia.org/wiki/Inca_Empire"> <pre> </pre> <p></a></a></span> ( xmlns: (v)==</h3> </h3> <p></a></ellipse></bod>

" urn: schemas-microsoft-com: vml (lang)=(en) > () ( (event.propertyName]> (VML Ellipse)

> <span> (> </p> <pre> (v : <pre> {{ behavior : <pre> (url) (<a href="https://en.wikipedia.org/wiki/Ancient_Egyptian_medicine"> (# default # VML) ) ; } <pre> <a href="#page-transition-filters"> (style) () ( </a><a href="https://web.archive.org/web/20070227195930/http://www.alexhopmann.com/xmlhttp.htm"> (head)> ( (oval) <span> (style) ==<pre> (position) <img alt="Clipboard Access Permission Prompt" src="http://schepp.dev/img/chemwriter_clipboard_prompt.png">: (absolute) ; (width) : ; (height) : <a href="#page-transition-filters">; <h3 id="page-transition-filters"> left <a href="https://en.wikipedia.org/wiki/Inca_Empire"> : [</a></h3></a></pre> <p></span>event<span>.</span>propertyName<span>] ; (top) () : [</span>event<span>.</span>propertyName<span>] ; <a href="#page-transition-filters"> " <span> (fillcolor) =</p> <pre> <a href="https://en.wikipedia.org/wiki/Ancient_Egyptian_medicine"> yellow [</a></pre> <p></span><span>'image'</span><span>] ” (strokecolor) </p> <h3 id="page-transition-filters">=</p> <pre> purple <a href="#page-transition-filters"> " <pre> (strokeweight) <a href="#page-transition-filters">= (2) <span> <h3 id="page-transition-filters">> ( (v: <a href="#the-era-of-the-trident-engine"> (oval)> <pre> ( (body) <h3 id="page-transition-filters">> <pre> </pre> </h3> <p></a></h3> <p></span> </a><a href="#page-transition-filters"> (html)> [</a></a></h3> <p></span>event<span>.</span>propertyName<span>] </p> <p> Both dialects look similar and seem equally unfamiliar to us web developers. </p> <p> (Data Binding) <a href="https://en.wikipedia.org/wiki/Inca_Empire"> </p> <h3 id="mhtml"> </h3> <p> Back since Internet Explorer 4.0 in 2011 you could embed data sources into your document. This could be done by referencing an (external CSV file <a href="https://en.wikipedia.org/wiki/Inca_Empire"> via <code> <a href="#the-era-of-the-trident-engine">: </a><a href="https://en.wikipedia.org/wiki/Inca_Empire"> (data) " (classid) </a><a href="#page-transition-filters">=</p> <pre> clsid: (C7BC4) (F - (D0-BC) - (C) A () (event<span>.</span>propertyName<span>] (name) <pre>= (DataURL) <h3 id="page-transition-filters"> (value) <img alt="Clipboard Access Permission Prompt" src="http://schepp.dev/img/chemwriter_clipboard_prompt.png">=(data.csv <a href="https://blogs.scientificamerican.com/observations/the-astronomical-genius-of-the-inca/"> ()>> ( </a><a href="https://phabricator.wikimedia.org/T203564"> (object </a></h3></pre> <p></span></a></code></a></p> <h3 id="page-transition-filters">> <a href="#page-transition-filters"> </a><a href="https://en.wikipedia.org/wiki/Heinrich_Schliemann"> </p> <p> Instead of a CSV file you could also (establish a connection to your database server </p> <p></a> (not suggested in writing mode :): <a href="https://en.wikipedia.org/wiki/Inca_Empire"> (data) " (classid) </a><a href="#page-transition-filters">=(clsid: BD) (C) - A3 - (D0 -) A </a><a href="https://en.wikipedia.org/wiki/Inca_Empire"> (C) FC (E) </a><a href="https://en.wikipedia.org/wiki/Inca_Empire"> <img alt="Clipboard Access Permission Prompt" src="http://schepp.dev/img/chemwriter_clipboard_prompt.png">> (Server) " (value) </a><a href="https://en.wikipedia.org/wiki/Heinrich_Schliemann"> (=</p> <h3 id="page-transition-filters"> http: // server </p> <h3 id="page-transition-filters">> <span> </p> <pre> name (=) <a href="https://blogs.scientificamerican.com/observations/the-astronomical-genius-of-the-inca/"> (Connect) [</a></pre> <p></span>event<span>.</span>propertyName<span>] (value) </p> <pre>=<h3 id="page-transition-filters"> " dsn=database; uid=guest; pwd=<h3 id="page-transition-filters">> <pre> </pre> </h3> </h3> <p></span> <a href="#page-transition-filters"> =</a><a href="#page-transition-filters"> " (SQL) (value) </p> <h3 id="page-transition-filters">=<a href="https://blogs.scientificamerican.com/observations/the-astronomical-genius-of-the-inca/"> select name from people ()> ( </a><a href="https://en.wikipedia.org/wiki/Ancient_Egyptian_medicine"> (object) </p> <h3 id="page-transition-filters">> <a href="https://en.wikipedia.org/wiki/Google_Chrome_Frame"> </p> <p> (Note how the <a href="https://en.wikipedia.org/wiki/Gears_(software)">) classid (attribute changes depending on the type of data.) </a></p> <p> And finally you could also reference an external XML file via <code> <code> tag ... <img alt="View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash" src="http://schepp.dev/img/natalya-letunova-gF8aHM445P4-unsplash.jpg"><a href="https://en.wikipedia.org/wiki/Inca_Empire"> (http: //localhost/xmlFile.xml </p> <h3 id="mhtml">> ( <a href="https://web.archive.org/web/20070227195930/http://www.alexhopmann.com/xmlhttp.htm"> (xml)> </p> <p> ... or use embedded inline XML in HTML as your data source: </p> <p> </a><a href="https://en.wikipedia.org/wiki/Inca_Empire"> </a></h3> <p></a></code></code></p> <p></a></h3> <p></a></h3> <p></a></h3> </h3> <p></a></h3> <p></a></span> =<span> data> () <a href="#page-transition-filters"> </a></span> > </a></span> </a></a></span>> Willa Galloway [

i] (name)>

       (>  (tortor@dictum.com) (  (email) >      

> 983 - 446 - [

event.propertyName] > Tenali ( (city)

>
  

(record) > (

  ...      (record)> 
  
...

(records) () ( (xml)>

      body>  ()  

That inlined XML was called “XML Data Islands” [

i]. and it worked similarly to how browsers nowadays handle SVG embedded in HTML or HTML embedded into an SVG by switching to another parser on the fly.

An XML data island is an XML document residing within an HTML page. This avoids having to write code (i.e. a script) just to load the XML document, or having to load it through a tag. Client side scripts can directly access these XML data islands. These XML data islands can be bound to HTML elements also.

Now that you had the data in your page you could use Internet Explorer's data binding to e.g. edit it:

(text) " (datasrc) =

# data (datafld)

=
  () (name   "

> 2-way Data Binding #

Not only could you bind data to an input, but also to arbitrary elements. And you could create a two-way data flow, just with declarative markup:

(data) " > (
       (  (name) 
>      

(xml) >

( Hello ,
  (datafld)    (=(“Metro Design - Microsoft, Public Domain (name)  

> ( (span)

> ! (h1)
>  

  (>  Your name:   (event.propertyName]  datasrc 
=  # data      (datafld)   (=

(name) () (onkeyup)==

" this.blur (); this.focus () "

> (label)>

   

The only reason there is onkeyup="this.blur (); this.focus ()" is to trigger data flow after each key press, as otherwise the other connected elements would only receive the updated value after the user left the input.

Data Grids (#

Internet Explorer also shipped with a native data grid implementation that you hooked up to the above data sources and which is built on top of the element. This was called (Tabular Data Control) . You would use the HTML attributes datafld View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash to map data fields to table columns, (dataformatas) to enable or disable HTML entity encoding of the contained data, and the datapagesize attribute to denote how many entries a page of the grid should show at once . And then there were the methods previousPage , (nextPage) , (firstPage) , lastPage to easily navigate through the pages.

(datagrid) " () datasrc= (# people) [

event.propertyName] datapagesize

=  

> ( [

event.propertyName] () ( [event.propertyName] ( (
(th)

> (Email) (th)> ()
  (>  (Phone) (  (th) >   
    >  (City) [event.propertyName]   (th) ()>  (  (tr) 
>    

> (>
(> [event.propertyName] span > () (td) (event.propertyName]> (email " > (td)>

  (>  ( (datafld)    (=(phone) >   
   (span) 
>  
  (      >  () ( = " (city)    

(span)> (td) > [event.propertyName] [event.propertyName] ( (tr) () ( (table) > ( (=(“datagrid.previousPage () () & lt; (previous) (
  
   button  onclick 
  

= (datagrid.nextPage ()> (next) "> & gt; ( (button)
>  
(Property Change Event) (# )

Internet Explorer featured an interesting propertychange event, which you could attach to DOM elements and which would trigger each time a property of it would change programmatically. This could have happened via setAttribute () or via object property access. This allowed to create observed / instrumented objects for similar use cases you could use ES Proxies nowadays. All you needed was a dummy DOM element with propertychange event applied: (store ">
  (   

[

event.propertyName] (
     (function View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash   (handler) 
 (  )  ({  

(if () (event) . (propertyName)===

  'onpropertychange'  )  ({    (return) 

; }

(alert)

 (  (event) (propertyName) ( )   '' s value was changed / set to "'    (store View from within the ruins of the Monument House of he Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria. Photo by Natalya Letunova on Unsplash  [event.propertyName]  

 ''  

;

}

store . onpropertychange=(handler) ;

store (test)=(true) () the store ) (test)=

  (false) ;  
store
(literal)= ({

} Clipboard Access Permission Prompt; (store . (literal)=() ({ (key) : ('value2') () ;

    (script)>   (Resize Events for DOM Elements     

Internet Explorer had plenty of unique events, but the most interesting one is the (element based) resize event) , available up until IE 9.

The onresize event fires for block and inline objects with layout, even if document or CSS (cascading style sheets) property values ​​are changed.

This event is basically in relation to (Resize Observer what mutation events are to the Mutation Observer . With the only difference to the usual events in that it triggered asynchronously, similarly to an observer.

element (onresize)==(function) (e)
)  

{ } (JavaScript Preloading) (#)

One interesting implementation of Internet Explorer was how it would load and execute JavaScript sources added via script. The code for that is the one we all know:

(var) (script)=(document) [event.propertyName] createElement (

'script'

 

; (var) (head =(document) . (getElementsByTagName) ()

' head '

)
;  

script (src)=('...')

; (head) appendChild

( (script) )

;

    

How other browser did it was to fetch and execute such a script in the moment it was appended to the DOM. Internet Explorer had a more clever approach: it splitted up both steps. Fetching happened as soon as the . Src property was assigned whereas only execution happened once the script was appended to the DOM. That way you could easily preload scripts without blocking the main thread. Something developers could only implement in a more complicated fashion in other browser, at least until we got Resource Hints

Internet Explorer was also the first browser to introduce the defer attribute for scripts.

Finding the currently executing script #

At some point, the HTML5 standard introduced (document.currentScript) which indicated to the element which was currently being executed. Why would you need this? For example to read out extra configuration like this one in the data-main attribute :

(scripts / require.js) " [

event.propertyName] (data-main) [event.propertyName] (=

 " (js / main  
  event.propertyName]    (script) [event.propertyName]>   

Somewhere inside scripts / require.js there would be this line:

(var) (main)=(document) (currentScript) getAttribute
  ( 
 'data -main '

;

Sadly, this only got implemented in Edge . What only a few people knew was that Internet Explorer had another mechanism in place which not only offered the same result, but that was also more in line with how a document would communicate if it was still loading or if it was fully interactive: scripts had a readyState property.

function (currentScript) ( ) ({ (var) (scripts) (=(document) (getElementsByTagName) [

event.propertyName] ( 'script'

 

) ; for
  (  ;  (i)  scripts .  (length 

; (i)

)

  ({
  
(if)
 ( (scripts) [

i] (readyState)===('interactive') ) ({

  (return) (scripts)  ;   
}  

}

(return) (null) ;

}

The readyState (property was dropped in Internet Explorer) which made this version the only one supporting neither . currentScript nor readyState (luckily, a genius named Adam Miller (found another way to polyfill it ). So what led to IE's downfall?

#

Looking at the above list, I would say that Microsoft was lightyears ahead of everyone else in regards to providing tools and solutions for architecting complex and delightful websites. Some syntax may look unfamiliar to us, but this is just because we are not used to it. Back in the days, XML was all the rage. And remember how you felt when you opened an SVG for the first time? Or when you saw ES6'es arrow notation? Or BEM? JSX? You probably had the same feelings.

One part of why Microsoft's ideas did not really catched on was that we developers just didn't get it. Most of us were amateurs and had no computer degree. Instead we were so busy learning about semantic markup and CSS that we totally missed the rest. And finally, I think too few people back then were fluent enough in JavaScript, let alone in architecting complex applications with JavaScript to appreciate things like HTML Components, Data Bindings or Default Behaviors. Not to speak of those weird XML sprinkles and VML.

The other reason could have been a lack of platforms to spread knowledge to the masses. The internet was still in its infancy, so there was no MDN, no Smashing Magazine, no Codepen, no Hackernoon, no Dev.to and almost no personal blogs with articles on these things. Except Webmonkey . There were also no conferences yet, where Microsoft devrel people could have spoken. And there was also no broadband and therefore no conference talks you could have watched on video. All there was, was mailing lists like "

The final nail in the coffin was that after the release of Internet Explorer 6, Microsoft decided to tightly couple new Internet Explorer releases to Windows releases. So they dismantled the Internet Explorer team

and integrated it into the Windows product team. Sadly, the Windows version in the making, Windows XP's successor with codename "Longhorn" (later Windows Vista), got massively delayed as development was so unfocused and chaotic that they are even needed to reset it This also delayed a new Internet Explorer release and left the web in a vacuum, with no one fixing bugs and improving existing technology. When Microsoft woke up five years later, it was already too late. W3C had developed new standards and the remaining other browser makers not only implemented them but also founded the WHATWG which brought even more innovations to the table. Microsoft lost its technical leadership, lost its market share, and never recovered from that period.

The cover photo of this post is shot from within the ruins of the

Monument House of the Bulgarian Communist Party, built on Buzludzha Peak in central Bulgaria

by Natalya Letunova on Unsplash

← Home Read More

About admin

Check Also

World's oceans were the warmest in 2019: Study – Telangana Today, Telanganatoday.com

World's oceans were the warmest in 2019: Study – Telangana Today, Telanganatoday.com

Beijing: The world’s oceans were the warmest in 2019 than any other time in recorded human history, especially between the surface and a depth of 2,000 metres, according to a study. The study, published in the journal Advances in Atmospheric Sciences, also found that the past ten years have been the warmest on record for…

Leave a Reply

Your email address will not be published. Required fields are marked *