Log : Console.log with style

This post has been automatically generated. I use this blog to collect links that I have bookmarked. All activity is automated.

README.md

Console.log with style

Demo

Features

  • Safely call log (instead of console.log) in any browser.
  • Use markdown syntax for quick formatting:
    • italiclog('this is *italic*')
    • boldlog('this word _bold_')
    • codelog('this word `code`')
  • Use a custom syntax to style text however you want: log('this is [c="color: red"]red[c]').

Screenshot

Something went wrong with that request. Please try again.

via Echo JS https://github.com/adamschwartz/log

Leave a comment

Filed under Auto

Setting up Sublime Text 2 (alexmaccaw.com)

This post has been automatically generated. I use this blog to collect links that I have bookmarked. All activity is automated.

maccman

JavaScript programmer, O’Reilly author, working at Stripe

  Svbtle April 9, 2013

I recently decided it was finally time to part ways with TextMate, my trusty companion for these last few years, and start the hunt for a new editor. After a quick Twitter poll the unanimous advice was that I should try Sublime Text 2.

After a few weeks of using Sublime Text I can safely say that it’s the best editor I’ve used. It’s fast, extendable and hasn’t ever crashed on me. That said, that no editor is perfect and Sublime Text does require a fair bit of initial configuration.


After you’ve downloaded & installed the editor, the first step to configuring Sublime Text 2 is to install the package manager. I’m hoping in future versions of the editor this package manager will come bundled, but for now it requires a separate installation. Run Sublime Text, Press ctrl ` (control backtick) to open the editor’s console, and paste in the code listed here.

Once the manager is set up, you can install packages with ⌘⇧p (command shift p) and typing Install Package.

Theme – Soda

Sublime’s initial look leaves a lot to be desired. However, luckily there’s a beautiful theme called Soda. To install Soda, open the package manager (⌘⇧p), type ‘Install Package ↵’, and then ‘Theme – Soda ↵’.

Screen Shot 2013-04-08 at 12.07.47 PM.png

To activate the theme, open Sublime’s preferences ⌘, (command comma), which is a JSON file, and set the "theme" key to "Soda Light.sublime-theme" (Remember to check commas).

{
  "theme": "Soda Light.sublime-theme"
}

You may have to restart the editor, or at least open a new window, for the theme to activate.

Extending the editor

There are a few other packages to install:

Follow the same steps as before to install the packages, ⌘⇧p and "Install package".

Tabs & Spaces

The default indentation style uses tabs instead of spaces, and it’s likely that you’ll want to switch this (unless you solely program in a language where that’s the convention, such as Go). Open Sublime’s preferences (Settings – User or ⌘,) and add:

{
  "tab_size": 2,
  "translate_tabs_to_spaces": true
}

If you’re anything like me, and dread trailing white space, then you should install the TrailingSpaces package. You’ll need to change the default preferences for the plugin too. Open TrailingSpace’s preferences (Preferences -> Package Settings -> TrailingSpaces -> Settings – User), and add:

{
  "trailing_spaces_include_current_line": false
}

Also add this to your global user preferences (⌘,):

 "trim_trailing_white_space_on_save": true

Key bindings

There’s a key binding I used the whole time in TextMate: ⌘ ctrl r to reveal the currently opened file in the sidebar. You can add this to Sublime by opening the key bindings preferences (Preferences -> Key Bindings – User) and adding:

[
  {"keys": ["ctrl+super+r"], "command": "reveal_in_side_bar"}
]

Sublime’s fuzzy search (⌘ t) is incredibly fast and convenient, and it’s my primary way of navigating around my projects. As well as navigating by file name, you can go to a particular line in a file by typing :123 (colon line number) or to a particular method by typing #name (hash method name).

Command line

Surprisingly Sublime Text doesn’t come with a easily accessible binary, since this is probably the primary way developers will open the editor. That said, you can easily add support by creating a symlink:

ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" /usr/bin/subl

I also use an alias in my ~/.bash_profile file, allowing me to easily open a directory from the terminal:

alias e='subl . &'

Icon

Sublime’s default icon is fairly ugly, but there are a few replacements on Dribbble. One of my favorites is by Elliot Jackson. To install it, download the icns file and replace the application’s icon:

$ mv ~/Downloads/st2.icns /Applications/Sublime\ Text\ 2.app/Contents/Resources/Sublime\ Text\ 2.icns 

sublime-text-2.png

Pasting

One suggestion from Jason Barry is to use ‘Paste and Indent’ for ⌘V instead of the standard ‘Paste’. This adjusts your indentation to automatically match the context it’s pasted in. To do this, put the following in your Key Bindings – User file:

[
  { "keys": ["super+v"], "command": "paste_and_indent" }, 
  { "keys": ["super+shift+v"], "command": "paste" } 
]

More packages

A few more packages you may find useful:

  • Git – Git blame/branch support
  • CoffeeScript – .coffee syntax highlighting
  • Eco – .eco syntax highlighting
  • Stylus – .styl syntax highlighting
  • Sass – .sass syntax highlighting
  • SublimeLinter – lint code as you type
  • GitGutter – show Git diffs in the gutter

Conclusion

So that’s a fair bit of setting up required for an editor, most of which you’d think would be the default configuration. Sublime Text 2 definitely needs a bit of polishing from a product perspective. The default website, icon, and theme are ugly to say the least, and it would be convenient to be able to install the editor through the App Store. A GUI for configuration would be a good idea as storing preferences in JSON files may appeal to programmers, but it definitely alienates designers.

That said it’s early days for the editor, and the core framework has clearly been built extremely well. It’s ridiculously fast, stable and very extendable. I love it and absolutely recommend you try it.

1,474

Kudos

Read this next

Abba – JavaScript a/b testing

←   Full blog

© 2013 SVBTLE

maccman

JavaScript programmer, O’Reilly author, working at Stripe

  Svbtle April 9, 2013

I recently decided it was finally time to part ways with TextMate, my trusty companion for these last few years, and start the hunt for a new editor. After a quick Twitter poll the unanimous advice was that I should try Sublime Text 2.

After a few weeks of using Sublime Text I can safely say that it’s the best editor I’ve used. It’s fast, extendable and hasn’t ever crashed on me. That said, that no editor is perfect and Sublime Text does require a fair bit of initial configuration.


After you’ve downloaded & installed the editor, the first step to configuring Sublime Text 2 is to install the package manager. I’m hoping in future versions of the editor this package manager will come bundled, but for now it requires a separate installation. Run Sublime Text, Press ctrl ` (control backtick) to open the editor’s console, and paste in the code listed here.

Once the manager is set up, you can install packages with ⌘⇧p (command shift p) and typing Install Package.

Theme – Soda

Sublime’s initial look leaves a lot to be desired. However, luckily there’s a beautiful theme called Soda. To install Soda, open the package manager (⌘⇧p), type ‘Install Package ↵’, and then ‘Theme – Soda ↵’.

Screen Shot 2013-04-08 at 12.07.47 PM.png

To activate the theme, open Sublime’s preferences ⌘, (command comma), which is a JSON file, and set the "theme" key to "Soda Light.sublime-theme" (Remember to check commas).

{
  "theme": "Soda Light.sublime-theme"
}

You may have to restart the editor, or at least open a new window, for the theme to activate.

Extending the editor

There are a few other packages to install:

Follow the same steps as before to install the packages, ⌘⇧p and "Install package".

Tabs & Spaces

The default indentation style uses tabs instead of spaces, and it’s likely that you’ll want to switch this (unless you solely program in a language where that’s the convention, such as Go). Open Sublime’s preferences (Settings – User or ⌘,) and add:

{
  "tab_size": 2,
  "translate_tabs_to_spaces": true
}

If you’re anything like me, and dread trailing white space, then you should install the TrailingSpaces package. You’ll need to change the default preferences for the plugin too. Open TrailingSpace’s preferences (Preferences -> Package Settings -> TrailingSpaces -> Settings – User), and add:

{
  "trailing_spaces_include_current_line": false
}

Also add this to your global user preferences (⌘,):

 "trim_trailing_white_space_on_save": true

Key bindings

There’s a key binding I used the whole time in TextMate: ⌘ ctrl r to reveal the currently opened file in the sidebar. You can add this to Sublime by opening the key bindings preferences (Preferences -> Key Bindings – User) and adding:

[
  {"keys": ["ctrl+super+r"], "command": "reveal_in_side_bar"}
]

Sublime’s fuzzy search (⌘ t) is incredibly fast and convenient, and it’s my primary way of navigating around my projects. As well as navigating by file name, you can go to a particular line in a file by typing :123 (colon line number) or to a particular method by typing #name (hash method name).

Command line

Surprisingly Sublime Text doesn’t come with a easily accessible binary, since this is probably the primary way developers will open the editor. That said, you can easily add support by creating a symlink:

ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" /usr/bin/subl

I also use an alias in my ~/.bash_profile file, allowing me to easily open a directory from the terminal:

alias e='subl . &'

Icon

Sublime’s default icon is fairly ugly, but there are a few replacements on Dribbble. One of my favorites is by Elliot Jackson. To install it, download the icns file and replace the application’s icon:

$ mv ~/Downloads/st2.icns /Applications/Sublime\ Text\ 2.app/Contents/Resources/Sublime\ Text\ 2.icns 

sublime-text-2.png

Pasting

One suggestion from Jason Barry is to use ‘Paste and Indent’ for ⌘V instead of the standard ‘Paste’. This adjusts your indentation to automatically match the context it’s pasted in. To do this, put the following in your Key Bindings – User file:

[
  { "keys": ["super+v"], "command": "paste_and_indent" }, 
  { "keys": ["super+shift+v"], "command": "paste" } 
]

More packages

A few more packages you may find useful:

  • Git – Git blame/branch support
  • CoffeeScript – .coffee syntax highlighting
  • Eco – .eco syntax highlighting
  • Stylus – .styl syntax highlighting
  • Sass – .sass syntax highlighting
  • SublimeLinter – lint code as you type
  • GitGutter – show Git diffs in the gutter

Conclusion

So that’s a fair bit of setting up required for an editor, most of which you’d think would be the default configuration. Sublime Text 2 definitely needs a bit of polishing from a product perspective. The default website, icon, and theme are ugly to say the least, and it would be convenient to be able to install the editor through the App Store. A GUI for configuration would be a good idea as storing preferences in JSON files may appeal to programmers, but it definitely alienates designers.

That said it’s early days for the editor, and the core framework has clearly been built extremely well. It’s ridiculously fast, stable and very extendable. I love it and absolutely recommend you try it.

1,474

Kudos

Read this next

Abba – JavaScript a/b testing

←   Full blog

© 2013 SVBTLE

via Hacker News 20 http://blog.alexmaccaw.com/sublime-text

Leave a comment

Filed under Auto

Icarus: New JS framework

Wrote a new Javascript framework. Do check it out.
# Icarus

Icarus is a JavaScript framework, that will enable you to write highly decoupled, yet structured web apps. Icarus is built on top of Twitter Flight. Icarus retains all the base functionalities of Flight. Icarus also uses a modified version of Laces.js for it's Model implementation. Some of the documentation has been borrowed from these two.

Why I wrote Icarus

Is Icarus an event-driven framework? Is Icarus a MV* framework? It is a little bit of both. The philosophy behind writing Icarus was to combine the best of both worlds. Icarus components are completely independent, and can communicate with one another, and with themselves using events. Icarus components also provide Models, which are similar to Models used in typical MV* frameworks. When Model data is added, removed, changed etc, events are fired to the component DOM with the data encapsulated in them. Custom functions may also be bound to these Model data events. Lastly, Icarus provides an option to sync the Model data with localStorage, so that it may be reinitialized when the page is reloaded.

Usage

The usage at the component level is exactly the same as Flight. Please refer to the Flight documentation for the same. To use the Icarus model, you will have to call the initModel method of the Icarus component. It is advisable to call this at the beginning of the after('initialize') function. A sample Icarus Component definition looks like this:

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.after('initialize', function () {
            this.initModel({});
        });
    }
    return defineComponent(myComponent);
});

Model methods

initModel

This method initializes the Model object. It takes one argument called options, which is a JS Object. The different options that can be set here are:

store: false by default. If set to true, the Model will sync with LocalStorage

localkey: A string value; It is the key used for LocalStorage

this.after('initialize', function () {
    this.initModel({store: true, localKey: 'icarusModel'});
});

removeModel

This method removes the Model object. Call this method before tearing down the Component. Though it is not mandatory, it is advisable to call this method to prevent memory leaks.

set

This method is used to add or change a property of the Model. It takes two arguments, the key and the value of the new data.

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.setCash = function(cash)
        {
            this.set('moneyz', 3000000);
        };
        this.after('initialize', function () {
            this.initModel({});
            this.on('paymentz', this.setCash);
        });
    }
    return defineComponent(myComponent);
});

The data that is set may be a single variable, an array, a Javascript object or a function that returns any of these. The function is recomputed whenever any of the Model values change. For example,

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.after('initialize', function () {
            this.initModel({});
            this.set('assets', 1000);
            this.set('liabilities', 500);
            this.set('totalCash', function() {return this.assets - this.liabilities;});
            this.set('assets', 2000);
            //totalCash is recalculated
        });
    }
    return defineComponent(myComponent);
});

Please see the Object and Array references for more details on these.

get

This method takes the property key as the argument, and returns the corresponding value.

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.setCash = function(cash)
        {
            var cash = this.get('moneyz');
            this.set('moneyz', cash*2);
        };
        this.after('initialize', function () {
            this.initModel({});
            this.on('paymentz', this.setCash);
        });
    }
    return defineComponent(myComponent);
});

remove

This method takes the key of the object to be removed as the argument, and removes the property from the Model.

bind

This method takes two arguments, the first is the type of change in the data, and the second is function to bind to this change. The function is executed every time the event is called. For different types of bindings, Please look at the Binding Types section.

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.after('initialize', function () {
            this.initModel({});
            this.set('totalCash', 50);
            this.bind('change:totalCash', function(data){ alert('I can haz attached!');});
        });
    }
    return defineComponent(myComponent);
});

Binding Types

The different types of bindings are:
1. 'add': called when a new entry is added.
1. 'remove': called when an entry is removed.
1. 'update': called when an existing property is changed.
1. 'change:(key)': called when an entry with the key is changed

The object passed has the following properties
1. 'name': name of the Binding type passed
1. 'key': key of the Object that generated this event
1. 'value': updated value

Functions can be bound to multiple events by separating the Binding types by a space. For example,

this.set('totalCash', 500);
this.bind('change:totalCash remove:totalCash', function (data){alert('Bound fn called');});

Events

Events with the same name and data as those in the Binding Types section are triggered to the component DOM node. Additional Events for add:(key), remove:(key) and update:(key) are also triggered. These can be handled by the component.

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.after('initialize', function () {
            this.initModel({});
            this.set('totalCash', 50);
            this.on('change:totalCash', function(event){ alert('I can haz attached!');});
        });
    }
    return defineComponent(myComponent);
});

The Event data can be found in Event.originalEvent.detail

Objects

When an Object with key-value properties is passed to the Model, each property is stored as a sub-model. Each of these sub-models will implement the methods get, set, remove and bind. Furthermore, Events will be triggered to the Component DOM node when data from these sub-models is added, removed or updated. These sub-models can be accessed by using get functions, and set using set functions in chains. Attributes could be accesed directly too, but use the set function to ensure proper binding and events. For example,

/*global define*/
define([
    '../../../lib/component'
], function (defineComponent) {
    function myComponent()
    {
        this.after('initialize', function () {
            this.initModel({});
            this.set('profile', {
                name: 'Ameya',
                keys: {
                    a: 1,
                    b: 2
                }
            });
            this.get('name'); //Returns Ameya
            this.get('keys'); //Returns sub-model
            this.get('keys').get('a'); //Returns keys->a
            //I could also write this.get('keys').a for the above line
            this.get('keys').set('b', 5); //Sets keys->b to 5
            //If I say this.get('keys').b=5, the bindings and events will not be triggered
        });
    }
    return defineComponent(myComponent);
});

Arrays

Arrays can be set as Model properties as well. You can modify array values directly, but it is adviced to use the set method to set values; If done directly, the bindings and events will not be executed.

Note: For arrays and objects, defining sub-attributes using functions that return a value will not work. Static values will have to be assigned.

Some Thoughts

  1. Though data binding is possible through both function-binding and events, one should try to use the function-bindings just to change data around, and the events for DOM manipulation, Ajax calls, external libraries etc.
  2. Do not include constantly changing objects such as DOM nodes into a Model. This will lead to a lot of events getting triggered, and data flying all over the place, and could freeze up the app.
  3. The data binding I have opted for is rather loose, and gives one the flexibility to choose how his/her app workflow is going to be.

What is next?

  1. Syncing the model data with a server through web-sockets with a polling fallback.
  2. Dynamic data for sub-models
  3. Lots more I guess! Still thinking 🙂

Do send in your feedback to ameya(dot)karve(at)gmail(dot)com. Special thanks to Nitin Madasu, Tanmai Gopal and Tom Hamshere for their help 🙂

Leave a comment

Filed under Tech

Write highly decoupled Webapps using Twitter Flight

Twitter recently open-sourced their webapp framework called Flight. I was starting on this webapp, and thought that I would give it a go. I have only worked on it for the last two-three weeks; it has left a very lasting impression on me though.

A different take from conventional MV* frameworks

The primary idea behind Flight is to divide the app into a number of “components”, which will interact with each other through events, and ideally, should be able to function independently. Flight also offers “mixins”, which can extend a component by adding more properties to it. The number of MVC/MV*  frameworks in JS has grown exponentially of late; Flight offers a very fresh way of looking at modern webapps. Steven Sanderson offers a very nice perspective on the various MV* frameworks around in his blog. Despite their differences, one common thing about all of these is that they impose their own structure on your code; some do this more than others. Flight is different in the sense that beyond the component definition, it gives a lot of flexibility to the user to use whatever he/she wishes to plug into the code without much of a pain. Flight is also inherently modular;  this leads to code getting very organized without any effort at all. It is also strongly in accordance with the DRY philosophy; Flight components can be attached to multiple DOM elements, Flight mixins can be added to multiple components, A single Flight component can have multiple mixins added to it.

How I used Flight

A little bit of a background about my app stack: It is a single page app. The various libraries I have used are:

  1. Require JS and AMD for loading modules:
  2. FlatIron Director for Routing: I wrote a hack over the original code to implement AMD
  3. Flight
  4. Bootstrap & a few of the Bootstrap Plugins
  5. JQuery
  6. Lo-Dash: Functionality of Underscore, but faster
  7. A bunch of JQuery plugins here and there
  8. Coffee Script and SASS

I call each single-page state as a “module”. Each module uses whatever components it needs. In the last two-three weeks, I have developed a solid structure through which I am using my components; I have been able to roll out code quicker than I have ever done. The file structure for each component looks like:

|–  model.js

|–  operations.js

|–  view.js

|–  templates

|– —  template1.txt

|– —  template2.txt

Here, model.js is the primary component file. operations.js and view.js are invoked as mixins into model.js. The idea behind this is to keep model.js clean; All my dirty work happens in operations.js (Various operations)  and view.js (All the DOM manipulation, templates are also loaded here). By defining further dependencies in operations.js and view.js, I can use any third part library that I wish to, and it will seamlessly integrate with my component. For example, I have not defined explicitly what engine I am going to use for templating; I could easily add whatever I am comfortable with without compromising on the overall structure.

Some Talking Points:

  • Do have a look at this account by Tom Hamshere on using Flight in refactoring TweetDeck. The post has a lot of insights on using Flight. I had a few nice discussions with Tom about Flight, and they have only strengthened my liking for Flight. 
  • Ean Schuessler talks about the “Models” in flight not being powerful enough. I gave this a long, hard thought. However, as Flight relies on events more than model data as such, data binding is completely. It is more of an event/DOM first approach; Similar to how Models are different in Angular as against  Backbone. In Backbone, the Views are derived from the Models; Here, it is the other way round.
  • Martin Gontovnikas also talks about the Model-View part as in the above point. He also mentions the lack of a Router. This, I feel is the essence of Flight really; It is not a full framework that will impose itself on you. It allows you to use whatever components you want to for the app; I, for instance have used FlatIron Director; I could have used Crossroads, or even the Backbone Router; that remains my call.
  • By dividing the app into a number of components, it makes it easier to test each component separately. Be careful about selecting your tester though; It should be able to support DOM events.
  • Flight is a relatively new framework, and there could probably be better ways to use it. If you have used Flight, and have some nice suggestions, do let me know. Also, I could share some of my code structure, if you would wish me to. Please feel free to give in feedback

3 Comments

Filed under Tech

Breaking down Amazon’s mega dropdown

This post has been automatically generated. I use this blog to collect links that I have bookmarked. All activity is automated.

The hover effects on Amazon’s big ‘ole “Shop by Department” mega dropdown are super fast. Look’it how quick each submenu fills in as your mouse moves down the list:

image

It’s instant. I got nerd sniped by this. Most dropdown menus have to include a bit of a delay when activating submenus. Here’s an old Khan Academy dropdown as an example:

image

See the delay? You need that, because otherwise when you try to move your mouse from the main menu to the submenu, the submenu will disappear out from under you like some sort of sick, unwinnable game of whack-a-mole. Enjoy this example from bootstrap’s dropdown menus:

image
I love bootstrap, don’t get it twisted. Just a good example of submenu frustration.

It’s easy to move the cursor from Amazon’s main dropdown to its submenus. You won’t run into the bootstrap bug. They get away with this by detecting the direction of the cursor’s path.

image
If the cursor moves into the blue triangle the currently displayed submenu will stay open for just a bit longer.

At every position of the cursor you can picture a triangle between the current mouse position and the upper and lower right corners of the dropdown menu. If the next mouse position is within that triangle, the user is probably moving their cursor into the currently displayed submenu. Amazon uses this for a nice effect. As long as the cursor stays within that blue triangle the current submenu will stay open. It doesn’t matter if the cursor hovers over “Appstore for Android” momentarily — the user is probably heading toward “Learn more about Cloud Drive.”

And if the cursor goes outside of the blue triangle, they instantly switch the submenu, giving it a really responsive feel.

So if you’re as geeky as me and think something this trivial is cool, I made a jQuery plugin that fires events when detecting this sort of directional menu aiming: jQuery-menu-aim. We’re using it in the new Khan Academy “Learn” menu:

image

I think it feels snappy. I’m not ashamed to copy Amazon. I’m sure this problem was solved years and years ago, forgotten, rediscovered, solved again, forgotten, rediscovered, solved again.

If anyone else on the planet ends up finding a use for jQuery-menu-aim, I’d be grateful to know what you think.


Thanks go to Ben Alpert for helping me understand the linear algebra / cross-product magic Amazon uses to detect movement inside the “blue triangle.” I ended up going w/ a cruder slope-based approach, mostly b/c I’ve lost all intuitive understanding of linear algebra. Sad. Need to watch more KA videos.

via Hacker News http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown

Leave a comment

Filed under Auto

“I Want Hue” – Colors for Data Scientists

This post has been automatically generated. I use this blog to collect links that I have bookmarked. All activity is automated.

See also our other tools at Médialab Tools!

And a huge thanks to these inspiring works:

Chroma.js

I massively use this excellent js library to convert colors. If you have not done it yet, look at this post. You’ll understand much useful things about color in dataviz.

ColorBrewer

Very famous tool, that showed the way few years ago. If you do not know it, you must take a look.

via Hacker News http://tools.medialab.sciences-po.fr/iwanthue/

Leave a comment

Filed under Auto

Turn your browser into a notepad with one line

This post has been automatically generated. I use this blog to collect links that I have bookmarked. All activity is automated.

Sometimes I just need to type garbage. Just to clear out my mind. Using editors to type such gibberish annoys me because it clutters my project workspace (I’m picky, I know).

So I do this. Since I live in the browser, I just open a new tab and type in the url tab.

data:text/html, <html contenteditable>

Voila, browser notepad.

You don’t need to remember it. It’s not rocket science. We are using the Data URI’s format and telling the browser to render an html (try “javascript:alert(‘Bazinga’);”). The content of said html is a simple html line with the html5 attribute contenteditable. This works only on modern browsers that understand this attribute. Click and type!

via Hacker News https://coderwall.com/p/lhsrcq

Leave a comment

Filed under Auto