Initial import
This commit is contained in:
commit
9f6fb1a2c5
32 changed files with 2330 additions and 0 deletions
66
2008.ie-valign.css
Normal file
66
2008.ie-valign.css
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* @group valignfix */
|
||||
/* ***************************************
|
||||
valignfix, by Anders Ytterström @ madr.se
|
||||
**************************************** */
|
||||
/*
|
||||
HTML fixture:
|
||||
.valign
|
||||
%div
|
||||
%div
|
||||
%h1
|
||||
%h2
|
||||
%img
|
||||
*/
|
||||
|
||||
/* @group ie8, ff, opera, safari
|
||||
===================================== */
|
||||
body > div {
|
||||
display:table;
|
||||
}
|
||||
*.valign {
|
||||
display:table-row;
|
||||
}
|
||||
*.valign > * {
|
||||
width:50%;
|
||||
display:table-cell;
|
||||
vertical-align:middle;
|
||||
}
|
||||
/* @end ie8, ff, opera, safari
|
||||
===================================== */
|
||||
|
||||
/* @group ie6,ie7
|
||||
===================================== */
|
||||
/*
|
||||
use this in CC file.
|
||||
Works only in standards mode.
|
||||
*/
|
||||
* html *.valign,
|
||||
*+html *.valign {
|
||||
position:relative;
|
||||
overflow:auto;
|
||||
}
|
||||
* html *.valign div,
|
||||
*+html *.valign div {
|
||||
position:absolute;
|
||||
top:50%;
|
||||
}
|
||||
* html *.valign div div,
|
||||
*+html *.valign div div {
|
||||
position:relative;
|
||||
top:-50%;
|
||||
}
|
||||
* html *.valign div div *,
|
||||
*+html *.valign div div * {
|
||||
position:static;
|
||||
top:0;
|
||||
}
|
||||
* html *.valign img,
|
||||
*+html *.valign img {
|
||||
float:right;
|
||||
}
|
||||
/* @end ie6, ie7
|
||||
===================================== */
|
||||
/* ****************************************
|
||||
/valignfix, by Anders Ytterström @ madr.se
|
||||
**************************************** */
|
||||
/* @end valignfix */
|
||||
4
2011.fix-outlook-2011-utf8-decoded-mails.php
Normal file
4
2011.fix-outlook-2011-utf8-decoded-mails.php
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
$subject = "=?UTF-8?B?" . base64_encode($subject) . "?=";
|
||||
|
||||
// mail( ... )
|
||||
67
2011.js.click-event-delegator.js
Normal file
67
2011.js.click-event-delegator.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*!
|
||||
light-weight click listener, v 1.0
|
||||
Copyright (c) 2010 by madr <http://madr.se>
|
||||
Licensed under the MIT license: http://en.wikipedia.org/wiki/MIT_License
|
||||
*/
|
||||
/*
|
||||
Usage:
|
||||
Alter the below snippet for your needs and put the modified snippet in a js-file or a <script> and add it to your document. If your webapp depends on libraries or other resources to load, you better keep that in mind.
|
||||
*/
|
||||
(function(document, undefined) {
|
||||
function investigate(elm){
|
||||
/*
|
||||
Change the content of this function
|
||||
to suit your web application.
|
||||
*/
|
||||
|
||||
/*
|
||||
EXAMPLE 0: do nothing until jQuery (or other libraries) is loaded.
|
||||
if (typeof window.jQuery == 'undefined') { return false; }
|
||||
*/
|
||||
|
||||
/*
|
||||
EXAMPLE 1: look for element type
|
||||
if (elm.nodeName == 'A') {
|
||||
// do stuff ...
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
EXAMPLE 2: look for id or other property
|
||||
if (elm.id == 'modal-window-opener') {
|
||||
// do stuff ...
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
EXAMPLE 3: sniffing a classname
|
||||
if (elm.className.match(/read-more/)) {
|
||||
// do stuff ...
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
return false; // default
|
||||
}
|
||||
|
||||
function clicklistener(evt){
|
||||
var event = evt || window.event,
|
||||
elm = event.target || window.srcElement,
|
||||
magic_did_happen = investigate(elm);
|
||||
|
||||
if (magic_did_happen) {
|
||||
if (window.event) { window.eventReturnValue = false; }
|
||||
else { evt.preventDefault(); }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (document.attachEvent) {
|
||||
document.attachEvent('onclick', clicklistener);
|
||||
} else {
|
||||
document.addEventListener('click', clicklistener, false);
|
||||
}
|
||||
})(document);
|
||||
96
2011.js.frontcontroller-skeleton.js
Normal file
96
2011.js.frontcontroller-skeleton.js
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, curly:true, browser:true, indent:2, maxerr:50 */
|
||||
|
||||
/*!
|
||||
front.js
|
||||
(c) 2011 Anders Ytterström
|
||||
front.js may be freely distributed under the MIT license.
|
||||
TODO: pushState support
|
||||
*/
|
||||
|
||||
/*
|
||||
USAGE: A route is defined by a path (could be a simple string or a regexp) and a callback (a function).
|
||||
|
||||
// static routes
|
||||
front("books", displayBooks);
|
||||
front("talks", displayTalks);
|
||||
front("comments", displayComments);
|
||||
|
||||
// dynamic routes
|
||||
front(/book:[\d+]$/, displayBookDetail);
|
||||
front(/talk:[\d+]$/, displayTalkDetail);
|
||||
front(/comment:[\d]$/, displayCommentDetail);
|
||||
|
||||
The frontcontroller should be executed when all dependencies are in place and the routes are configured.
|
||||
|
||||
front.run(); // defaults to location.hash -> http://example.com
|
||||
front.run("book:12"); // goto book 12 -> http://example.com#!book:12
|
||||
|
||||
location.hash is altered everytime front.run is executed.
|
||||
*/
|
||||
|
||||
(function (global) {
|
||||
"use strict";
|
||||
var i, _regexps = [], _statics = [];
|
||||
|
||||
function addRoute(path, callback) {
|
||||
if (typeof path !== "string") { // regexp
|
||||
_regexps.push([ path, callback ]);
|
||||
} else {
|
||||
_statics.push([ path, callback ]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function dispatch(path) {
|
||||
// set path
|
||||
if (typeof path === "undefined") {
|
||||
path = location.hash || "";
|
||||
path = path.replace(/^#/, '').replace(/^!/, '');
|
||||
}
|
||||
|
||||
// cleanup
|
||||
var action, args;
|
||||
|
||||
// static routes lookup
|
||||
i = _statics.length;
|
||||
while (i--) {
|
||||
if (_statics[i][0] === path) {
|
||||
action = _statics[i][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// regexp routes lookup unless a static action was defined.
|
||||
if (typeof action !== "function") {
|
||||
i = _regexps.length;
|
||||
while (i--) {
|
||||
args = args = path.match(_regexps[i][0]);
|
||||
if (args) {
|
||||
action = _regexps[i][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// execute action and update hash unless the action is still undefined
|
||||
if (typeof action === "function") {
|
||||
if (args instanceof Array) {
|
||||
args.shift();
|
||||
if (args.length === 1) { args = args[0]; }
|
||||
}
|
||||
|
||||
action(args);
|
||||
|
||||
path = (path.length ? '#!': '') + path;
|
||||
|
||||
if (location.hash !== path) {
|
||||
location.hash = path;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // for click events.
|
||||
}
|
||||
|
||||
global.front = addRoute;
|
||||
global.front.run = dispatch;
|
||||
})(this);
|
||||
14
2011.js.hex2rgb.js
Normal file
14
2011.js.hex2rgb.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
function hex2rgb(hex, opacity) {
|
||||
var rgb = hex.replace('#', '').match(/(.{2})/g);
|
||||
|
||||
var i = 3;
|
||||
while (i--) {
|
||||
rgb[i] = parseInt(rgb[i], 16);
|
||||
}
|
||||
|
||||
if (typeof opacity == 'undefined') {
|
||||
return 'rgb(' + rgb.join(', ') + ')';
|
||||
}
|
||||
|
||||
return 'rgba(' + rgb.join(', ') + ', ' + opacity + ')';
|
||||
};
|
||||
17
2011.js.rel-ymd-date-str.js
Normal file
17
2011.js.rel-ymd-date-str.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
function adate(daysFromNow) {
|
||||
var date, datestr, mm, dd;
|
||||
datestr = new Date().getTime();
|
||||
if (!!daysFromNow) {
|
||||
datestr += (1000 * 60 * 60 * 24 * daysFromNow);
|
||||
}
|
||||
date = new Date(datestr);
|
||||
mm = date.getMonth() + '';
|
||||
if (mm.length == 1) {
|
||||
mm = '0' + mm;
|
||||
}
|
||||
dd = date.getDate() + '';
|
||||
if (dd.length == 1) {
|
||||
dd = '0' + dd;
|
||||
}
|
||||
return date.getFullYear() + '-' + mm + '-' + dd;
|
||||
}
|
||||
45
2011.rake-target-generate-favicons-apple-touch-icons.rb
Normal file
45
2011.rake-target-generate-favicons-apple-touch-icons.rb
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# example use:
|
||||
# rake favicons["../img/origin.png"]
|
||||
#
|
||||
# Output:
|
||||
# ./apple-touch-icon-114x114-precomposed.png
|
||||
# ./apple-touch-icon-114x114.png
|
||||
# ./apple-touch-icon-57x57-precomposed.png
|
||||
# ./apple-touch-icon-57x57.png
|
||||
# ./apple-touch-icon-72x72-precomposed.png
|
||||
# ./apple-touch-icon-72x72.png
|
||||
# ./apple-touch-icon-precomposed.png
|
||||
# ./apple-touch-icon.png
|
||||
# ./favicon.ico
|
||||
|
||||
require "RMagick"
|
||||
|
||||
desc "Generates favicons and webapp icons"
|
||||
task :favicons, :origin do |t, args|
|
||||
name = "apple-touch-icon-%dx%d.png"
|
||||
name_pre = "apple-touch-icon-%dx%d-precomposed.png"
|
||||
|
||||
FileList["*apple-touch-ico*.png"].each do |img|
|
||||
File.delete img
|
||||
end
|
||||
|
||||
FileList["*favicon.ico"].each do |img|
|
||||
File.delete img
|
||||
end
|
||||
|
||||
FileList[args.origin].each do |img|
|
||||
puts "creating favicon.ico"
|
||||
|
||||
Magick::Image::read(img).first.resize(16, 16).write("favicon.ico")
|
||||
|
||||
[114, 57, 72].each do |size|
|
||||
puts "creating %d * %d icons" % [size, size]
|
||||
Magick::Image::read(img).first.resize(size, size).write(name % [size, size]).write(name_pre % [size, size])
|
||||
end
|
||||
|
||||
puts "creating backward-compatible icons"
|
||||
|
||||
cp name_pre % [57, 57], "apple-touch-icon.png"
|
||||
cp name_pre % [57, 57], "apple-touch-icon-precomposed.png"
|
||||
end
|
||||
end
|
||||
119
2011.ruby.posterous-weekly-links-simplified.rb
Normal file
119
2011.ruby.posterous-weekly-links-simplified.rb
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'net/https'
|
||||
require "rexml/document"
|
||||
require "date"
|
||||
require 'net/smtp'
|
||||
|
||||
# delicious
|
||||
@username = "YOU"
|
||||
@password = "secr3t"
|
||||
# smtp settings, asuming gmail
|
||||
@smtp_server = 'smtp.gmail.com'
|
||||
@smtp_port = 587
|
||||
@smtp_user = "YOU@gmail.com"
|
||||
@smtp_passwd = "secr3t"
|
||||
# outgoing mail
|
||||
@mail_from = "YOU@gmail.com"
|
||||
@mail_from_alias = "YOU"
|
||||
@mail_subject = "Värt att uppmärksamma, vecka #{(Date.today.cweek)} ((tags: läsvärt))"
|
||||
# posterous
|
||||
@posterous_email = "YOU@posterous.com"
|
||||
|
||||
#######
|
||||
|
||||
def get_description
|
||||
description = gets.chomp
|
||||
|
||||
return description
|
||||
end
|
||||
|
||||
# found at: http://blog.jerodsanto.net/2009/02/a-simple-ruby-method-to-send-emai/
|
||||
def send_email(to, opts={})
|
||||
opts[:server] ||= 'localhost'
|
||||
opts[:from] ||= @mail_from
|
||||
opts[:from_alias] ||= @mail_from_alias
|
||||
opts[:subject] ||= @mail_subject
|
||||
opts[:body] ||= "test"
|
||||
|
||||
msg = <<END_OF_MESSAGE
|
||||
From: #{opts[:from_alias]} <#{opts[:from]}>
|
||||
To: <#{to}>
|
||||
Subject: #{opts[:subject]}
|
||||
|
||||
#{opts[:body]}
|
||||
END_OF_MESSAGE
|
||||
|
||||
# found at: http://stackoverflow.com/questions/1183743/ruby-getting-netsmtp-working-with-gmail
|
||||
smtp = Net::SMTP.new @smtp_server, @smtp_port
|
||||
smtp.enable_starttls
|
||||
smtp.start(@smtp_server, @smtp_user, @smtp_passwd, :login)
|
||||
smtp.send_message(msg, to, to)
|
||||
smtp.finish
|
||||
end
|
||||
|
||||
#######
|
||||
|
||||
begin
|
||||
resp = href = "";
|
||||
|
||||
puts "From date, YYYY-MM-DD"
|
||||
from_date = gets.chomp
|
||||
|
||||
puts "To date, YYYY-MM-DD"
|
||||
to_date = gets.chomp
|
||||
|
||||
puts " "
|
||||
|
||||
url = "/v1/posts/all?fromdt=#{from_date}T00:00:00Z&todt=#{to_date}T23:59:59Z"
|
||||
descriptions = []
|
||||
|
||||
http = Net::HTTP.new("api.del.icio.us", 443)
|
||||
|
||||
http.use_ssl = true
|
||||
http.start do |http|
|
||||
req = Net::HTTP::Get.new(url, {"User-Agent" =>
|
||||
"juretta.com RubyLicious 0.2"} )
|
||||
req.basic_auth(@username, @password)
|
||||
response = http.request(req)
|
||||
resp = response.body
|
||||
end
|
||||
|
||||
# XML Document
|
||||
doc = REXML::Document.new(resp)
|
||||
|
||||
#doc.root.elements.each do |elem|
|
||||
# puts " \n"
|
||||
# puts elem.attributes['description']
|
||||
# puts "(" + elem.attributes['href'] + ")"
|
||||
# puts " =>"
|
||||
# descriptions.push(get_description)
|
||||
#end
|
||||
|
||||
body_txt = "<markdown>\n"
|
||||
|
||||
i = 0
|
||||
doc.root.elements.each do |elem|
|
||||
if elem.attributes['extended'] != ''
|
||||
body_txt += "* [" + elem.attributes['description'] + "]("+ elem.attributes['href'] + ") \n " +
|
||||
elem.attributes['extended'] + "\n" #descriptions[i] + "\n"
|
||||
#i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
body_txt += "</markdown>\n#end"
|
||||
|
||||
puts "\n\n"
|
||||
puts body_txt
|
||||
puts "\n\n"
|
||||
|
||||
#puts "Sending to posterous ... "
|
||||
#send_email @posterous_email, :body => body_txt
|
||||
#puts "Done."
|
||||
#puts " "
|
||||
|
||||
rescue SocketError
|
||||
raise "Host " + host + " nicht erreichbar"
|
||||
rescue REXML::ParseException => e
|
||||
print "error parsing XML " + e.to_s
|
||||
end
|
||||
119
2011.ruby.posterous-weekly-links.rb
Normal file
119
2011.ruby.posterous-weekly-links.rb
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'net/https'
|
||||
require "rexml/document"
|
||||
require "date"
|
||||
require 'net/smtp'
|
||||
|
||||
# delicious
|
||||
@username = "YOU"
|
||||
@password = "secr3t"
|
||||
# smtp settings, asuming gmail
|
||||
@smtp_server = 'smtp.gmail.com'
|
||||
@smtp_port = 587
|
||||
@smtp_user = "YOU@gmail.com"
|
||||
@smtp_passwd = "s3cr3t"
|
||||
# outgoing mail
|
||||
@mail_from = "YOU@gmail.com"
|
||||
@mail_from_alias = "Name Surname"
|
||||
@mail_subject = "Värt att uppmärksamma, vecka #{(Date.today.cweek)-1}"
|
||||
# posterous
|
||||
@posterous_email = "YOU@posterous.com"
|
||||
|
||||
#######
|
||||
|
||||
def get_description
|
||||
description = gets.chomp
|
||||
|
||||
return description
|
||||
end
|
||||
|
||||
# found at: http://blog.jerodsanto.net/2009/02/a-simple-ruby-method-to-send-emai/
|
||||
def send_email(to, opts={})
|
||||
opts[:server] ||= 'localhost'
|
||||
opts[:from] ||= @mail_from
|
||||
opts[:from_alias] ||= @mail_from_alias
|
||||
opts[:subject] ||= @mail_subject
|
||||
opts[:body] ||= "test"
|
||||
|
||||
msg = <<END_OF_MESSAGE
|
||||
From: #{opts[:from_alias]} <#{opts[:from]}>
|
||||
To: <#{to}>
|
||||
Subject: #{opts[:subject]}
|
||||
|
||||
#{opts[:body]}
|
||||
END_OF_MESSAGE
|
||||
|
||||
# found at: http://stackoverflow.com/questions/1183743/ruby-getting-netsmtp-working-with-gmail
|
||||
smtp = Net::SMTP.new @smtp_server, @smtp_port
|
||||
smtp.enable_starttls
|
||||
smtp.start(@smtp_server, @smtp_user, @smtp_passwd, :login)
|
||||
smtp.send_message(msg, to, to)
|
||||
smtp.finish
|
||||
end
|
||||
|
||||
#######
|
||||
|
||||
begin
|
||||
resp = href = "";
|
||||
|
||||
puts "From date, YYYY-MM-DD"
|
||||
from_date = gets.chomp
|
||||
|
||||
puts "To date, YYYY-MM-DD"
|
||||
to_date = gets.chomp
|
||||
|
||||
puts " "
|
||||
|
||||
url = "/v1/posts/all?fromdt=#{from_date}T00:00:00Z&todt=#{to_date}T23:59:59Z"
|
||||
descriptions = []
|
||||
|
||||
http = Net::HTTP.new("api.del.icio.us", 443)
|
||||
|
||||
http.use_ssl = true
|
||||
http.start do |http|
|
||||
req = Net::HTTP::Get.new(url, {"User-Agent" =>
|
||||
"juretta.com RubyLicious 0.2"} )
|
||||
req.basic_auth(@username, @password)
|
||||
response = http.request(req)
|
||||
resp = response.body
|
||||
end
|
||||
|
||||
# XML Document
|
||||
doc = REXML::Document.new(resp)
|
||||
|
||||
doc.root.elements.each do |elem|
|
||||
puts " \n"
|
||||
puts elem.attributes['description']
|
||||
puts "(" + elem.attributes['href'] + ")"
|
||||
puts " =>"
|
||||
descriptions.push(get_description)
|
||||
end
|
||||
|
||||
body_txt = "<markdown>\n"
|
||||
|
||||
i = 0
|
||||
doc.root.elements.each do |elem|
|
||||
if elem.attributes['extended'] != ''
|
||||
body_txt += "* [" + elem.attributes['description'] + "]("+ elem.attributes['href'] + ") \n " +
|
||||
descriptions[i] + "\n" #elem.attributes['extended'] + "\n"
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
body_txt += "</markdown>\n#end"
|
||||
|
||||
puts "\n\n"
|
||||
puts body_txt
|
||||
puts "\n\n"
|
||||
|
||||
puts "Sending to posterous ... "
|
||||
#send_email @posterous_email, :body => body_txt
|
||||
puts "Done."
|
||||
puts " "
|
||||
|
||||
rescue SocketError
|
||||
raise "Host " + host + " nicht erreichbar"
|
||||
rescue REXML::ParseException => e
|
||||
print "error parsing XML " + e.to_s
|
||||
end
|
||||
291
2012.js.autocomplete.js
Normal file
291
2012.js.autocomplete.js
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
By Anders Ytterström 2012.
|
||||
|
||||
Example use:
|
||||
<script src="autocomplete.js"></script>
|
||||
<script>
|
||||
var values = ["Hansi", "Andre", "The Omen", "Marcus", "Prince Charles"],
|
||||
callback = function (k) {
|
||||
console.log(k);
|
||||
};
|
||||
|
||||
autocomplete("bg", values, callback);
|
||||
</script>
|
||||
*/
|
||||
|
||||
/*jslint indent: 2, maxlen: 90, browser: true */
|
||||
var autocomplete = function (id, values, callback) {
|
||||
"use strict";
|
||||
var autoCompleteTimer,
|
||||
stopDefaultAction,
|
||||
getPosition,
|
||||
field,
|
||||
initAutoComplete,
|
||||
keydownAutoComplete,
|
||||
generateDropdown,
|
||||
autoComplete,
|
||||
mouseoverDropdown,
|
||||
mouseoutDropdown,
|
||||
mousedownDropdown,
|
||||
assignMouseListeners,
|
||||
blurAutoComplete,
|
||||
closeDropdown;
|
||||
|
||||
stopDefaultAction = function (event) {
|
||||
event.returnValue = false;
|
||||
if (typeof event.preventDefault !== "undefined") {
|
||||
event.preventDefault();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
getPosition = function (theElement) {
|
||||
var positionX = 0,
|
||||
positionY = 0;
|
||||
while (theElement !== null) {
|
||||
positionX += theElement.offsetLeft;
|
||||
positionY += theElement.offsetTop;
|
||||
theElement = theElement.offsetParent;
|
||||
}
|
||||
return [positionX, positionY];
|
||||
};
|
||||
|
||||
initAutoComplete = function () {
|
||||
field = document.getElementById(id);
|
||||
field.setAttribute("autocomplete", "off");
|
||||
if (window.attachEvent) {
|
||||
field.attachEvent("onkeydown", keydownAutoComplete);
|
||||
} else {
|
||||
field.addEventListener("keydown", keydownAutoComplete);
|
||||
}
|
||||
field.onblur = function () {
|
||||
blurAutoComplete();
|
||||
};
|
||||
};
|
||||
|
||||
keydownAutoComplete = function (event) {
|
||||
var target = event.target || event.srcElement,
|
||||
autoCompleteDropdown,
|
||||
childLis,
|
||||
selected,
|
||||
i,
|
||||
max,
|
||||
inputRanges;
|
||||
if (typeof event === "undefined") {
|
||||
event = window.event;
|
||||
}
|
||||
switch (event.keyCode) {
|
||||
case 9: // tab
|
||||
case 13: // enter
|
||||
case 16: // shift
|
||||
case 17: // ctrl
|
||||
case 18: // alt
|
||||
case 20: // caps lock
|
||||
case 27: // esc
|
||||
case 33: // page up
|
||||
case 34: // page down
|
||||
case 35: // end
|
||||
case 36: // home
|
||||
case 37: // left arrow
|
||||
case 39: // right arrow
|
||||
break;
|
||||
case 38: // up arrow
|
||||
autoCompleteDropdown = document.getElementById("autoCompleteDropdown");
|
||||
if (autoCompleteDropdown !== null) {
|
||||
childLis = autoCompleteDropdown.childNodes;
|
||||
selected = false;
|
||||
for (i = 0, max = childLis.length; i < max; i += 1) {
|
||||
if (childLis[i].className === "hover") {
|
||||
selected = true;
|
||||
if (i > 0) {
|
||||
childLis[i].className = "";
|
||||
childLis[i - 1].className = "hover";
|
||||
target.value = childLis[i - 1].firstChild.nodeValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!selected) {
|
||||
childLis[0].className = "hover";
|
||||
target.value = childLis[0].firstChild.nodeValue;
|
||||
}
|
||||
}
|
||||
stopDefaultAction(event);
|
||||
break;
|
||||
case 40: // down arrow
|
||||
autoCompleteDropdown = document.getElementById("autoCompleteDropdown");
|
||||
if (autoCompleteDropdown !== null) {
|
||||
childLis = autoCompleteDropdown.childNodes;
|
||||
selected = false;
|
||||
for (i = 0, max = childLis.length; i < max; i += 1) {
|
||||
if (childLis[i].className === "hover") {
|
||||
selected = true;
|
||||
|
||||
if (i < childLis.length - 1) {
|
||||
childLis[i].className = "";
|
||||
childLis[i + 1].className = "hover";
|
||||
target.value = childLis[i + 1].firstChild.nodeValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!selected) {
|
||||
childLis[0].className = "hover";
|
||||
target.value = childLis[0].firstChild.nodeValue;
|
||||
}
|
||||
}
|
||||
stopDefaultAction(event);
|
||||
break;
|
||||
case 8: // backspace
|
||||
case 46: // delete
|
||||
if (typeof autoCompleteTimer !== "undefined") {
|
||||
clearTimeout(autoCompleteTimer);
|
||||
}
|
||||
autoCompleteTimer = setTimeout(function () {
|
||||
generateDropdown(false);
|
||||
}, 500);
|
||||
break;
|
||||
default:
|
||||
if (typeof autoCompleteTimer !== "undefined") {
|
||||
clearTimeout(autoCompleteTimer);
|
||||
}
|
||||
target = event.target || event.srcElement;
|
||||
inputRanges = "false";
|
||||
if (typeof target.createTextRange !== "undefined"
|
||||
|| typeof target.setSelectionRange !== "undefined") {
|
||||
inputRanges = "true";
|
||||
}
|
||||
autoCompleteTimer = setTimeout(function () {
|
||||
generateDropdown(inputRanges);
|
||||
}, 500);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
assignMouseListeners = function (e) {
|
||||
e.onmouseover = function () {
|
||||
mouseoverDropdown(this);
|
||||
};
|
||||
e.mouseout = function () {
|
||||
mouseoutDropdown(this);
|
||||
};
|
||||
e.mousedown = function () {
|
||||
mousedownDropdown(this);
|
||||
};
|
||||
};
|
||||
|
||||
generateDropdown = function (doAutoComplete) {
|
||||
closeDropdown();
|
||||
var input = document.getElementById(id),
|
||||
newUl = document.createElement("div"),
|
||||
newLi,
|
||||
i,
|
||||
max = values.length;
|
||||
newUl.setAttribute("id", "autoCompleteDropdown");
|
||||
newUl.autoCompleteInput = input;
|
||||
newUl.style.position = "absolute";
|
||||
newUl.style.left = getPosition(input)[0] + "px";
|
||||
newUl.style.top = getPosition(input)[1] + input.offsetHeight - 2 + "px";
|
||||
newUl.style.width = input.offsetWidth - 3 + "px";
|
||||
for (i = 0; i < max; i += 1) {
|
||||
if (values[i].indexOf(input.value) === 0) {
|
||||
newLi = document.createElement("button");
|
||||
newLi.innerHTML = values[i];
|
||||
assignMouseListeners(newLi);
|
||||
newUl.appendChild(newLi);
|
||||
}
|
||||
}
|
||||
if (newUl.firstChild !== null) {
|
||||
document.getElementsByTagName("body")[0].appendChild(newUl);
|
||||
}
|
||||
if (typeof doAutoComplete !== "undefined" && doAutoComplete) {
|
||||
autoComplete();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
autoComplete = function () {
|
||||
var input = document.getElementById(id),
|
||||
cursorMidway = false,
|
||||
range,
|
||||
originalValue,
|
||||
autoCompleteDropdown;
|
||||
if (typeof document.selection !== "undefined") {
|
||||
range = document.selection.createRange();
|
||||
if (range.move("character", 1) !== 0) {
|
||||
cursorMidway = true;
|
||||
}
|
||||
} else if (typeof input.selectionStart !== "undefined"
|
||||
&& input.selectionStart < input.value.length) {
|
||||
cursorMidway = true;
|
||||
}
|
||||
originalValue = input.value;
|
||||
autoCompleteDropdown = document.getElementById("autoCompleteDropdown");
|
||||
if (autoCompleteDropdown !== null && !cursorMidway) {
|
||||
autoCompleteDropdown.firstChild.className = "hover";
|
||||
input.value = autoCompleteDropdown.firstChild.firstChild.nodeValue;
|
||||
if (typeof input.createTextRange !== "undefined") {
|
||||
range = input.createTextRange();
|
||||
range.moveStart("character", originalValue.length);
|
||||
range.select();
|
||||
} else if (typeof input.setSelectionRange !== "undefined") {
|
||||
input.setSelectionRange(originalValue.length, input.value.length);
|
||||
}
|
||||
if (autoCompleteDropdown.childNodes.length === 1) {
|
||||
setTimeout(function () {
|
||||
closeDropdown();
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
mouseoverDropdown = function (target) {
|
||||
var childLis, i, max;
|
||||
while (target.nodeName.toLowerCase() !== "button") {
|
||||
target = target.parentNode;
|
||||
}
|
||||
childLis = target.parentNode.childNodes;
|
||||
max = childLis.length;
|
||||
for (i = 0; i < max; i += 1) {
|
||||
childLis[i].className = "";
|
||||
}
|
||||
target.className = "hover";
|
||||
return true;
|
||||
};
|
||||
|
||||
mouseoutDropdown = function (target) {
|
||||
while (target.nodeName.toLowerCase() !== "button") {
|
||||
target = target.parentNode;
|
||||
}
|
||||
target.className = "";
|
||||
return true;
|
||||
};
|
||||
|
||||
mousedownDropdown = function (target) {
|
||||
while (target.nodeName.toLowerCase() !== "button") {
|
||||
target = target.parentNode;
|
||||
}
|
||||
target.parentNode.autoCompleteInput.value = target.firstChild.nodeValue;
|
||||
closeDropdown();
|
||||
return true;
|
||||
};
|
||||
|
||||
blurAutoComplete = function () {
|
||||
if (typeof autoCompleteTimer !== "undefined") {
|
||||
clearTimeout(autoCompleteTimer);
|
||||
}
|
||||
closeDropdown();
|
||||
callback(field.value);
|
||||
return true;
|
||||
};
|
||||
|
||||
closeDropdown = function () {
|
||||
var autoCompleteDropdown = document.getElementById("autoCompleteDropdown");
|
||||
if (autoCompleteDropdown !== null) {
|
||||
autoCompleteDropdown.parentNode.removeChild(autoCompleteDropdown);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
initAutoComplete();
|
||||
};
|
||||
8
2012.js.get-week.js
Normal file
8
2012.js.get-week.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* getWeek function, return current week number from a `Date` object.
|
||||
*/
|
||||
getWeek = function (date) {
|
||||
var onejan = new Date(date.getFullYear(), 0, 1);
|
||||
return Math.ceil((((date - onejan) / 86400000)
|
||||
+ onejan.getDay()) / 7);
|
||||
};
|
||||
97
2012.js.match-media-conditional-exec.js
Normal file
97
2012.js.match-media-conditional-exec.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*jslint devel:true, browser:true, indent:2, maxlen: 70 */
|
||||
(function (window) {
|
||||
"use strict";
|
||||
var Condition, Listener, watcher;
|
||||
|
||||
// Requires window.matchMedia:
|
||||
// https://developer.mozilla.org/en/DOM/window.matchMedia
|
||||
if (typeof window.matchMedia === "undefined") { return; }
|
||||
|
||||
Condition = function (mq, callback) {
|
||||
this.mq = window.matchMedia(mq);
|
||||
this.callback = function () {
|
||||
callback.call();
|
||||
};
|
||||
};
|
||||
Condition.prototype.matches = function () {
|
||||
return this.mq.matches;
|
||||
};
|
||||
|
||||
Listener = function () {
|
||||
this.callbacks = [];
|
||||
this.cbLen = 0;
|
||||
this.runned = 0;
|
||||
};
|
||||
Listener.prototype.waitFor = function (condition) {
|
||||
this.callbacks.push(condition);
|
||||
this.cbLen += 1;
|
||||
};
|
||||
Listener.prototype.walk = function () {
|
||||
var toRun = [],
|
||||
i = this.cbLen,
|
||||
cb = this.callbacks;
|
||||
|
||||
while (i) {
|
||||
i -= 1;
|
||||
if (cb[i]) {
|
||||
if (cb[i].matches()) {
|
||||
toRun.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toRun;
|
||||
};
|
||||
Listener.prototype.execute = function (toRun) {
|
||||
var i = toRun.length;
|
||||
|
||||
while (i) {
|
||||
i -= 1;
|
||||
this.callbacks[toRun[i]].callback.call();
|
||||
this.callbacks[toRun[i]] = '';
|
||||
this.runned += 1;
|
||||
}
|
||||
};
|
||||
Listener.prototype.investigate = function () {
|
||||
var toRun;
|
||||
toRun = this.walk();
|
||||
|
||||
if (toRun.length) { this.execute(toRun); }
|
||||
|
||||
if (this.runned === this.cbLen) {
|
||||
window.onresize = "";
|
||||
}
|
||||
};
|
||||
Listener.prototype.install = function () {
|
||||
var callback, wait, that = this;
|
||||
|
||||
callback = function () {
|
||||
that.investigate();
|
||||
};
|
||||
|
||||
window.onresize = function () {
|
||||
clearTimeout(wait);
|
||||
wait = setTimeout(callback, 333);
|
||||
};
|
||||
|
||||
this.investigate();
|
||||
};
|
||||
|
||||
watcher = new Listener();
|
||||
|
||||
watcher.waitFor(new Condition(
|
||||
"all and (min-width: 801px)",
|
||||
function () {
|
||||
console.log("load delicicous bookmarks (we have room!)");
|
||||
}
|
||||
));
|
||||
|
||||
watcher.waitFor(new Condition(
|
||||
"all and (min-width: 1281px)",
|
||||
function () {
|
||||
console.log("load heavy pictures (we are on desktop!)");
|
||||
}
|
||||
));
|
||||
|
||||
watcher.install();
|
||||
}(window));
|
||||
10
2012.js.sprintf.js
Normal file
10
2012.js.sprintf.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
Thank you, almighty!
|
||||
http://www.nczonline.net/blog/2011/10/11/simple-maintainable-templating-with-javascript/
|
||||
*/
|
||||
function sprintf(text){
|
||||
var i=1, args=arguments;
|
||||
return text.replace(/%s/g, function(pattern){
|
||||
return (i < args.length) ? args[i++] : "";
|
||||
});
|
||||
}
|
||||
50
2012.python.download-hmtl-page-behind-login.py
Normal file
50
2012.python.download-hmtl-page-behind-login.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
'''
|
||||
Example htmldump_config.py:
|
||||
|
||||
url = "http://localhost:5000"
|
||||
login = "admin@adeprimo.se"
|
||||
password = "app161770"
|
||||
|
||||
def pages_to_validate():
|
||||
pages = [
|
||||
# event registration
|
||||
('event-start', '/events/start/'),
|
||||
('event-form', '/events/create'),
|
||||
('events', '/events'),
|
||||
('event-edit', '/events/view/'),
|
||||
|
||||
return pages
|
||||
'''
|
||||
import mechanize
|
||||
import re
|
||||
from htmldump_config import pages_to_validate, url, login, password
|
||||
|
||||
url = url + "%s"
|
||||
filepattern = "../static/htmldumps/%s.html"
|
||||
|
||||
print "creating fake browser env"
|
||||
br = mechanize.Browser()
|
||||
print "--- done"
|
||||
print "logging in as admin"
|
||||
br.open(url % "/login")
|
||||
br.select_form(nr=0)
|
||||
br["email"] = login
|
||||
br["password"] = password
|
||||
br.submit()
|
||||
print "--- now logged in as %s" % login
|
||||
|
||||
def htmldump(name, doc):
|
||||
with open(filepattern % name, "w") as f:
|
||||
f.write(doc)
|
||||
f.close()
|
||||
|
||||
def begin_download(pages):
|
||||
for filename, url_path in pages:
|
||||
print "downloading: %s" % url_path
|
||||
print " to: %s.html" % filename
|
||||
response = br.open(url % url_path)
|
||||
htmldump(filename, response.read())
|
||||
|
||||
pages = pages_to_validate()
|
||||
|
||||
begin_download(pages)
|
||||
14
2012.scss.column-separator.scss
Normal file
14
2012.scss.column-separator.scss
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* vertical ruler using pseudo-elements */
|
||||
@mixin columnseparator {
|
||||
@extend .relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
background: #eee;
|
||||
left: 681px;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
18
2012.scss.folded-corner.scss
Normal file
18
2012.scss.folded-corner.scss
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// folded box
|
||||
@mixin folded ($size: 10px, $y: 30px, $background: $grey4) {
|
||||
line-height: $y;
|
||||
height: $y;
|
||||
margin-left: ($size * -1);
|
||||
text-indent: $size;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
border-left: $size solid $pagebg;
|
||||
border-top: $size solid darken($background, 80%);
|
||||
float: left;
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: ($size * -1);
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
24
2013.bash.new-mamp-vhost.sh
Normal file
24
2013.bash.new-mamp-vhost.sh
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# usage: ./adp-new-vhost <name>
|
||||
#
|
||||
mampdir=/Applications/MAMP
|
||||
confdir=$mampdir/conf/apache/extra/vhosts
|
||||
codedir=~/Code
|
||||
mampport=80
|
||||
|
||||
cat <<end > $confdir/$1.conf
|
||||
<VirtualHost *:$mampport>
|
||||
ServerName $1
|
||||
DocumentRoot $codedir/$1
|
||||
|
||||
<Directory "$codedir/$1">
|
||||
AllowOverride all
|
||||
Options -Indexes
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
end
|
||||
|
||||
echo <passwd> | sudo -- sh -c "echo '127.0.0.1 $1' >> /etc/hosts"
|
||||
26
2013.python.embed-png-in-css-as-datauri.py
Normal file
26
2013.python.embed-png-in-css-as-datauri.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env python
|
||||
import base64, re, argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='CSS-Embed PNG images as data-URIs')
|
||||
parser.add_argument('files', metavar='file', nargs="+", type=str,
|
||||
help='path to a css file')
|
||||
|
||||
img = re.compile("url\('?\"?(.*\.png)'?\"?\)")
|
||||
repl = "url(data:image/png;base64,%s)"
|
||||
|
||||
cssfiles = parser.parse_args().files
|
||||
|
||||
if "swapcase" in dir(["a"]):
|
||||
cssfiles = [cssfiles]
|
||||
|
||||
for cssfile in cssfiles:
|
||||
css = open(cssfile, "r").read()
|
||||
|
||||
for image_path in img.findall(css):
|
||||
data = base64.b64encode(open(image_path, "r").read())
|
||||
pattern = "url\('?\"?%s'?\"?\)" % image_path
|
||||
css = re.sub(re.compile(pattern), repl % data, css)
|
||||
|
||||
f = open(cssfile, "w")
|
||||
f.write(css)
|
||||
f.close()
|
||||
100
2013.ruby.ftp-upload.rb
Normal file
100
2013.ruby.ftp-upload.rb
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
require "rubygems"
|
||||
require 'net/ftp'
|
||||
require 'stringio'
|
||||
|
||||
ftp = ""
|
||||
username = ""
|
||||
passwd = ""
|
||||
root_dir = "../../../../"
|
||||
current_rev_file = root_dir + "__CURRENT_VERSION__"
|
||||
|
||||
root_dir = ""
|
||||
|
||||
# new rev is either HEAD or a commit, set by ARGV
|
||||
new_rev = ""
|
||||
new_rev = ARGV.first unless ARGV.first != nil
|
||||
cmd_newrev = "git show -s --format=\"%%h %%s (%%ar)\" %s" % new_rev
|
||||
new_rev = `#{cmd_newrev}`
|
||||
|
||||
# old rev (current in production) are stored in a file.
|
||||
old_rev = File.open(current_rev_file, "r").read
|
||||
|
||||
cmd = "git diff --name-status %s %s" % [old_rev.split(" ").first, new_rev.split(" ").first]
|
||||
|
||||
files = `#{cmd}`
|
||||
|
||||
# change to root
|
||||
Dir.chdir root_dir
|
||||
|
||||
class Net::FTP
|
||||
def puttextcontent(content, remotefile, &block)
|
||||
f = StringIO.new(content)
|
||||
begin
|
||||
storlines("STOR " + remotefile, f, &block)
|
||||
ensure
|
||||
f.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def chkdir(ftp, parents)
|
||||
path = []
|
||||
|
||||
parents.each do |d|
|
||||
parent_path = path.join("/")
|
||||
path << d
|
||||
unless ftp.list(parent_path).any? { |dir| dir.match(d) }
|
||||
ftp.mkdir(path.join("/"))
|
||||
puts "[chkdir] created dir: %s" % path.join("/")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def put_file(ftp, path)
|
||||
parents = path.split("/")
|
||||
parents.pop
|
||||
|
||||
chkdir ftp, parents
|
||||
|
||||
if path.match(".png")
|
||||
ftp.putbinaryfile(path, path)
|
||||
else
|
||||
ftp.puttextfile(path, path)
|
||||
end
|
||||
|
||||
puts "[put_file] %s" % path
|
||||
end
|
||||
|
||||
puts "\nCurrent rev in Production: %s" % old_rev
|
||||
puts " The new rev: %s\n" % new_rev
|
||||
|
||||
if old_rev == new_rev
|
||||
puts "Everything is up to date, exiting"
|
||||
exit
|
||||
end
|
||||
|
||||
# list files to be changed in ftp prod
|
||||
puts "files changed:", files, ""
|
||||
|
||||
# connect to ftp server
|
||||
ftp = Net::FTP.new(ftp)
|
||||
ftp.login username, passwd
|
||||
remote = ftp.chdir root_dir
|
||||
|
||||
# make changes
|
||||
files.each_line do |file|
|
||||
flag, file = file.split("\t")
|
||||
file.strip!
|
||||
|
||||
if flag == "A" || flag == "M"
|
||||
put_file ftp, file
|
||||
end
|
||||
|
||||
if flag == "D"
|
||||
ftp.delete file
|
||||
end
|
||||
end
|
||||
|
||||
File.open(current_rev_file, "w").write(new_rev)
|
||||
|
||||
ftp.close
|
||||
40
2013.ruby.html-validator.rb
Normal file
40
2013.ruby.html-validator.rb
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
require "rubygems"
|
||||
require 'living-validator'
|
||||
require 'uri'
|
||||
|
||||
url = ARGV.first
|
||||
files = ARGV.slice(1, 9999)
|
||||
stop_at = files.length
|
||||
i = 1
|
||||
|
||||
def colorize(text, color_code)
|
||||
"\e[#{color_code}m#{text}\e[0m"
|
||||
end
|
||||
|
||||
def red(text); colorize(text, 31); end
|
||||
def green(text); colorize(text, 32); end
|
||||
|
||||
valid = true
|
||||
|
||||
files.each do |file|
|
||||
puts '[%d/%d] %s%s:' % [i, stop_at, url, file]
|
||||
i += 1
|
||||
result = LivingValidator::Validator.check '%s%s' % [url, file]
|
||||
unless result == false
|
||||
if result.errorCount > 0
|
||||
result.errors.each do |error|
|
||||
puts red("%d:%d %s" % [error["lastLine"], error["lastColumn"], error["message"]])
|
||||
end
|
||||
|
||||
valid = false
|
||||
else
|
||||
puts green "valid"
|
||||
end
|
||||
else
|
||||
puts red("FAILED")
|
||||
end
|
||||
end
|
||||
|
||||
exit 1 unless valid == true
|
||||
|
||||
exit 0
|
||||
94
2014.js.geolocation-pos2px.html
Normal file
94
2014.js.geolocation-pos2px.html
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body { margin: 0; }
|
||||
div { position: absolute; width: 20px; height: 20px; border-radius: 50%; background: red; }
|
||||
</style>
|
||||
<img src="mupp2.png" alt="" width="2500" height="2500">
|
||||
<div hidden></div>
|
||||
<script>
|
||||
/*jslint browser: true */
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
if (navigator.geolocation !== undefined) {
|
||||
var Map,
|
||||
map,
|
||||
mapImg,
|
||||
upperLeftBound = { lat: 63.184472, lng: 14.616544 },
|
||||
lowerRightBound = { lat: 63.171043, lng: 14.646316 };
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
Map = function (x, y, upperLeftBounds, lowerRightBounds) {
|
||||
this.dims = {x: x, y: y};
|
||||
this.bounds = [upperLeftBounds, lowerRightBounds];
|
||||
this.spot = document.getElementsByTagName("div")[0];
|
||||
};
|
||||
|
||||
Map.prototype.convert = function (lat, lng) {
|
||||
var MAP_WIDTH, MAP_HEIGHT, e, w, n, s, nsspan, ewspan, nspix, ewpix, x, y;
|
||||
|
||||
MAP_WIDTH = this.dims.x;
|
||||
MAP_HEIGHT = this.dims.y;
|
||||
|
||||
e = this.bounds[1].lat;
|
||||
w = this.bounds[0].lat;
|
||||
n = this.bounds[0].lng;
|
||||
s = this.bounds[1].lng;
|
||||
|
||||
nsspan = Math.abs(n - s);
|
||||
ewspan = Math.abs(w - e);
|
||||
|
||||
nspix = MAP_HEIGHT / nsspan;
|
||||
ewpix = MAP_WIDTH / ewspan;
|
||||
|
||||
x = (Math.abs(w - lat)) * ewpix;
|
||||
y = (Math.abs(n - lng)) * nspix;
|
||||
|
||||
return {
|
||||
top: parseInt(x, 10),
|
||||
left: parseInt(y, 10)
|
||||
};
|
||||
};
|
||||
|
||||
Map.prototype.center = function (lat, lng) {
|
||||
var lt,
|
||||
tl = this.convert(lat, lng),
|
||||
w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
|
||||
h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||
|
||||
lt = {
|
||||
left: tl.left - (w / 2),
|
||||
top: tl.top - (h / 2)
|
||||
};
|
||||
|
||||
if (lt.left < 0) { lt.left = 0; }
|
||||
if (lt.top < 0) { lt.top = 0; }
|
||||
|
||||
window.scrollTo(lt.left, lt.top);
|
||||
};
|
||||
|
||||
Map.prototype.showPos = function (lat, lng) {
|
||||
var pos = this.convert(lat, lng);
|
||||
this.spot.hidden = false;
|
||||
this.spot.style.top = pos.top - 10 + "px";
|
||||
this.spot.style.left = pos.left - 10 + "px";
|
||||
};
|
||||
|
||||
mapImg = document.getElementsByTagName("img")[0];
|
||||
|
||||
map = new Map(mapImg.width, mapImg.height, upperLeftBound, lowerRightBound);
|
||||
|
||||
// initial scroll for the map
|
||||
navigator.geolocation.getCurrentPosition(function (position) {
|
||||
map.center(position.coords.latitude, position.coords.longitude);
|
||||
});
|
||||
|
||||
// update position on map
|
||||
var watchID = navigator.geolocation.watchPosition(function (position) {
|
||||
map.showPos(position.coords.latitude, position.coords.longitude);
|
||||
});
|
||||
}
|
||||
}());
|
||||
</script>
|
||||
143
2015.grunt.htmldev-checklist.js
Normal file
143
2015.grunt.htmldev-checklist.js
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
The Following folder structure is required:
|
||||
|
||||
./
|
||||
./dist
|
||||
app.js
|
||||
app.min.js
|
||||
app.min.zipped.js
|
||||
design.css
|
||||
design.min.css
|
||||
design.min.zipped.css
|
||||
./src
|
||||
./src/js
|
||||
.src/js/core
|
||||
.src/js/modules
|
||||
init.js
|
||||
design.less
|
||||
./styleguide
|
||||
./styleguide/template
|
||||
index.html
|
||||
section-1.html
|
||||
section-2.html
|
||||
section-3.html
|
||||
section-5.html
|
||||
*/
|
||||
module.exports = function(grunt) {
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
csslint: {
|
||||
strict: {
|
||||
src: ['dist/design.css']
|
||||
}
|
||||
},
|
||||
compress: {
|
||||
main: {
|
||||
options: {
|
||||
mode: 'gzip'
|
||||
},
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
src: ['dist/app.min.js'],
|
||||
dest: '',
|
||||
ext: '.min.zipped.js'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
src: ['dist/design.min.css'],
|
||||
dest: '',
|
||||
ext: '.min.zipped.css'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
dist: {
|
||||
src: ['src/js/core/*.js', 'src/js/modules/*.js', 'src/js/init.js'],
|
||||
dest: 'dist/app.js',
|
||||
},
|
||||
},
|
||||
devserver: {
|
||||
"options": {
|
||||
"port": 8888
|
||||
},
|
||||
server: {}
|
||||
},
|
||||
htmllint: {
|
||||
all: ["styleguide/*.html"]
|
||||
},
|
||||
jasmine: {
|
||||
pivotal: {
|
||||
src: ['src/js/*/*.js'],
|
||||
options: {
|
||||
specs: 'spec/*Spec.js',
|
||||
helpers: 'spec/*Helper.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
jslint: {
|
||||
client: {
|
||||
src: [
|
||||
'src/js/*/*.js',
|
||||
'src/js/*.js'
|
||||
],
|
||||
exclude: [],
|
||||
}
|
||||
},
|
||||
kss: {
|
||||
options: {
|
||||
template: 'styleguide/template', // create this manually: `kss-node -i styleguide/template`
|
||||
includeType: 'less'
|
||||
},
|
||||
files: {
|
||||
src: ['src/less'],
|
||||
dest: 'styleguide'
|
||||
}
|
||||
},
|
||||
less: {
|
||||
development: {
|
||||
files: {
|
||||
"dist": "src/less"
|
||||
},
|
||||
files: {
|
||||
"dist/design.css": "src/less/design.less"
|
||||
}
|
||||
},
|
||||
production: {
|
||||
options: {
|
||||
cleancss: true
|
||||
},
|
||||
files: {
|
||||
"dist/design.min.css": "src/less/design.less"
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
|
||||
},
|
||||
build: {
|
||||
src: 'dist/app.js',
|
||||
dest: 'dist/app.min.js'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-csslint');
|
||||
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-devserver');
|
||||
grunt.loadNpmTasks('grunt-html');
|
||||
grunt.loadNpmTasks('grunt-jslint');
|
||||
grunt.loadNpmTasks('grunt-kss');
|
||||
|
||||
grunt.registerTask('deploy', ['less:production', 'less:development', 'concat', 'uglify', 'compress', 'kss']);
|
||||
grunt.registerTask('test', ['htmllint', 'csslint', 'jslint', 'jasmine']);
|
||||
grunt.registerTask('default', ['test']);
|
||||
};
|
||||
66
2015.js.infinite-scroll.js
Normal file
66
2015.js.infinite-scroll.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*jslint browser: true, indent: 4 */
|
||||
/*
|
||||
Example use of ScrollGuard: a simple, unobtrusive lazy loader.
|
||||
|
||||
Each time the user scrolled to the bottom of the page:
|
||||
|
||||
1. Look if there is content to load (lookForNextPage)
|
||||
2. If new content, get content using Ajax (getNextPage)
|
||||
3. Append the new content and do some polish (appencContent)
|
||||
|
||||
*/
|
||||
(function (g) {
|
||||
"use strict";
|
||||
var lookForNextPage,
|
||||
getNextPage,
|
||||
appendContent;
|
||||
|
||||
if (g.ScrollGuard === undefined) {
|
||||
throw new Error("scrollguard.js is required!");
|
||||
}
|
||||
|
||||
appendContent = function (content) {
|
||||
var body, rows, i, max, newContent, table;
|
||||
|
||||
body = document.createElement("div");
|
||||
body.innerHTML = content;
|
||||
|
||||
newContent = document.createDocumentFragment();
|
||||
rows = body.querySelectorAll(".main-c table tr");
|
||||
|
||||
for (i = 1, max = rows.length; i < max; i += 1) {
|
||||
newContent.appendChild(rows[i]);
|
||||
}
|
||||
|
||||
table = document.querySelector(".main-c table").tBodies[0];
|
||||
table.replaceChild(newContent, table.querySelector("tr.pagination"));
|
||||
};
|
||||
|
||||
lookForNextPage = function () {
|
||||
var nextPage = document.getElementById("pager-next");
|
||||
|
||||
if (nextPage) {
|
||||
getNextPage(nextPage.href);
|
||||
}
|
||||
};
|
||||
|
||||
getNextPage = function (href) {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.status === 200 || request.status === 304) {
|
||||
appendContent(request.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.open("GET", href, true);
|
||||
request.send(null);
|
||||
};
|
||||
|
||||
if (document.getElementById("pager-next")) {
|
||||
g.ScrollGuard.add(lookForNextPage, -1);
|
||||
g.ScrollGuard.start();
|
||||
}
|
||||
}(this));
|
||||
25
2015.js.pirate-speech.js
Normal file
25
2015.js.pirate-speech.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* Kopiera och klistra in i Firebug eller Dev Tools, ändra sista raden. */
|
||||
(function (str) {
|
||||
"use strict";
|
||||
var blacklist = ' aeiouyöäåAEIOUYÖÄÅ';
|
||||
|
||||
function ify(c) {
|
||||
return c + "o" + c.toLowerCase();
|
||||
}
|
||||
|
||||
function pirate(str) {
|
||||
var chars = str.split(""),
|
||||
i = chars.length;
|
||||
|
||||
while (i) {
|
||||
i -= 1;
|
||||
if (!blacklist.match(chars[i])) {
|
||||
chars[i] = ify(chars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return chars.join("");
|
||||
}
|
||||
|
||||
return pirate(str);
|
||||
}("Det här ska jag säga"));
|
||||
113
2015.js.responsive-loader.js
Normal file
113
2015.js.responsive-loader.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*jslint browser: true, indent: 4 */
|
||||
/*global updateCanvas: true */
|
||||
(function (g) {
|
||||
"use strict";
|
||||
var lookForNextPage,
|
||||
getNextPage,
|
||||
appendContent,
|
||||
loadManually,
|
||||
manual,
|
||||
loader,
|
||||
working;
|
||||
|
||||
if (g.ScrollGuard === undefined) {
|
||||
throw new Error("scrollguard.js is required!");
|
||||
}
|
||||
|
||||
appendContent = function (content) {
|
||||
var body, rows, i, max, newContent, table;
|
||||
body = document.createElement("div");
|
||||
body.innerHTML = content;
|
||||
|
||||
newContent = document.createDocumentFragment();
|
||||
rows = body.querySelectorAll(".main-c table tr");
|
||||
|
||||
for (i = 1, max = rows.length; i < max; i += 1) {
|
||||
newContent.appendChild(rows[i]);
|
||||
}
|
||||
|
||||
table = document.querySelector(".main-c table").tBodies[0];
|
||||
table.replaceChild(newContent, table.querySelector("tr.pagination"));
|
||||
|
||||
if (typeof(updateCanvas) === "function") {
|
||||
updateCanvas();
|
||||
}
|
||||
|
||||
loadManually();
|
||||
};
|
||||
|
||||
loadManually = function () {
|
||||
var button;
|
||||
|
||||
button = document.getElementById("load-manually");
|
||||
|
||||
if (button) {
|
||||
if (!document.getElementById("pager-next")) {
|
||||
button.parentNode.removeChild(button);
|
||||
}
|
||||
|
||||
button.onclick = function () {
|
||||
var nextPage = document.getElementById("pager-next");
|
||||
|
||||
if (nextPage) {
|
||||
getNextPage(nextPage.href);
|
||||
button.parentNode.replaceChild(loader.cloneNode(), button);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
manual = function () {
|
||||
var style, elm;
|
||||
|
||||
elm = document.getElementById("load-manually");
|
||||
|
||||
if (!elm) { return false; }
|
||||
|
||||
style = window.getComputedStyle(elm, null);
|
||||
return style.getPropertyValue("display") !== "none";
|
||||
};
|
||||
|
||||
lookForNextPage = function () {
|
||||
if (!manual()) {
|
||||
var nextPage = document.getElementById("pager-next");
|
||||
|
||||
if (nextPage) {
|
||||
getNextPage(nextPage.href);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getNextPage = function (href) {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
if (working === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
working = true;
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
working = false;
|
||||
if (request.status === 200 || request.status === 304) {
|
||||
appendContent(request.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.open("GET", href, true);
|
||||
request.send(null);
|
||||
};
|
||||
|
||||
loadManually();
|
||||
|
||||
loader = document.createElement("img");
|
||||
loader.style.paddingTop = "14px";
|
||||
loader.src = "/templates/wide/css/images/loader.gif";
|
||||
|
||||
if (document.getElementById("pager-next")) {
|
||||
g.ScrollGuard.add(lookForNextPage, -1);
|
||||
g.ScrollGuard.start();
|
||||
}
|
||||
}(this));
|
||||
116
2015.js.scrollguard.js
Normal file
116
2015.js.scrollguard.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*jslint browser: true, indent: 4 */
|
||||
(function (g) {
|
||||
"use strict";
|
||||
var ScrollGuard,
|
||||
started = false,
|
||||
lock = false,
|
||||
timer,
|
||||
breakpoints = [],
|
||||
getDocHeight,
|
||||
getScrollTop;
|
||||
|
||||
// found at http://james.padolsey.com/javascript/
|
||||
// get-document-height-cross-browser/
|
||||
getDocHeight = function () {
|
||||
return Math.max(
|
||||
Math.max(document.body.scrollHeight,
|
||||
document.documentElement.scrollHeight),
|
||||
Math.max(document.body.offsetHeight,
|
||||
document.documentElement.offsetHeight),
|
||||
Math.max(document.body.clientHeight,
|
||||
document.documentElement.clientHeight)
|
||||
);
|
||||
};
|
||||
|
||||
// found at http://stackoverflow.com/questions/871399/
|
||||
// cross-browser-method-for-detecting-the-scrolltop-of-the-browser-g
|
||||
getScrollTop = function () {
|
||||
var b, d;
|
||||
if (g.pageYOffset !== undefined) {
|
||||
return g.pageYOffset;
|
||||
}
|
||||
|
||||
b = document.body;
|
||||
d = document.documentElement;
|
||||
|
||||
d = (d.clientHeight) ? d : b;
|
||||
|
||||
return d.scrollTop;
|
||||
};
|
||||
|
||||
ScrollGuard = {
|
||||
// from: a distance from top, given in pixels (required)
|
||||
// to: a distance from top, given in pixels (optional)
|
||||
//
|
||||
// special cases:
|
||||
// from = -1 will instead look if bottom of page
|
||||
// is visible.
|
||||
add: function (callback, from, to) {
|
||||
var range;
|
||||
|
||||
if (from === -1) {
|
||||
range = function (topPos) {
|
||||
return getDocHeight() - topPos <= g.innerHeight;
|
||||
};
|
||||
} else {
|
||||
if (to === undefined) {
|
||||
range = function (topPos) {
|
||||
return topPos >= from;
|
||||
};
|
||||
} else {
|
||||
range = function (topPos) {
|
||||
return topPos >= from && topPos <= to;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
breakpoints.push({
|
||||
within: range,
|
||||
callback: callback
|
||||
});
|
||||
},
|
||||
fire: function (pos) {
|
||||
var max = breakpoints.length,
|
||||
i,
|
||||
bp;
|
||||
|
||||
lock = true;
|
||||
|
||||
for (i = 0; i < max; i += 1) {
|
||||
bp = breakpoints[i];
|
||||
|
||||
if (bp.within(pos)) {
|
||||
bp.callback();
|
||||
}
|
||||
}
|
||||
|
||||
lock = false;
|
||||
},
|
||||
start: function () {
|
||||
if (started) { return; }
|
||||
|
||||
var callback = function () {
|
||||
if (lock === false) {
|
||||
clearTimeout(timer);
|
||||
|
||||
timer = setTimeout(function () {
|
||||
ScrollGuard.fire(getScrollTop());
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
if (g.attachEvent) {
|
||||
g.attachEvent('onscroll', callback);
|
||||
} else {
|
||||
g.addEventListener('scroll', callback, false);
|
||||
}
|
||||
|
||||
started = true;
|
||||
|
||||
// initial call to catch initial scroll positions
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
g.ScrollGuard = ScrollGuard;
|
||||
}(this));
|
||||
61
2015.php.view-engine.php
Normal file
61
2015.php.view-engine.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* view.php
|
||||
*
|
||||
* simple view class, template-based.
|
||||
* @todo indent markup using tidy?
|
||||
*
|
||||
* $Rev$
|
||||
* $Author$
|
||||
* $Date$
|
||||
*/
|
||||
class view
|
||||
{
|
||||
protected $hasLayout;
|
||||
private $file;
|
||||
|
||||
public function __construct( $file_path ) {
|
||||
if(!file_exists($file_path)) {
|
||||
throw new Exception('file ' . $file_path . ' does not exist!', 666);
|
||||
} else {
|
||||
$this->file = $file_path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the view
|
||||
*
|
||||
* @return $HTMLSource the compiled view
|
||||
*/
|
||||
public function compile($registry = false) {
|
||||
if($registry === false){
|
||||
$registry =& registry::getInstance();
|
||||
}
|
||||
$user =& user::getInstance();
|
||||
foreach($registry as $k=>$v){
|
||||
$$k = $v;
|
||||
}
|
||||
ob_start();
|
||||
require $this->file;
|
||||
$body = ob_get_clean();
|
||||
|
||||
(isset($contentType)) ? http_response::content($contentType) : http_response::content(CONTENT_TYPE);
|
||||
|
||||
$isFragment = isset($this->isFragment);
|
||||
|
||||
if(defined('LAYOUT') && !$isFragment){
|
||||
ob_start();
|
||||
require LAYOUT;
|
||||
$body = ob_get_clean();
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
public function isFragment() {
|
||||
$this->isFragment = true;
|
||||
}
|
||||
|
||||
function __toString() {
|
||||
return __CLASS__;
|
||||
}
|
||||
}
|
||||
19
2015.python.color-contrast-foreground-color.py
Normal file
19
2015.python.color-contrast-foreground-color.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
'''
|
||||
based on: http://24ways.org/2010/calculating-color-contrast/
|
||||
accepts hex colors with 3 or 6 chars. hash-char is optional.
|
||||
'''
|
||||
def get_contrast_yiq(hex_color):
|
||||
hex_color = hex_color.replace("#", "")
|
||||
|
||||
if len(hex_color) == 3:
|
||||
hex_color = "".join([c + c for c in hex_color])
|
||||
|
||||
r = int(hex_color[0:2], 16)
|
||||
g = int(hex_color[2:4], 16)
|
||||
b = int(hex_color[4:6], 16)
|
||||
|
||||
yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000
|
||||
|
||||
if yiq >= 128:
|
||||
return 'black'
|
||||
return 'white'
|
||||
293
2016.less.boilerplate.less
Normal file
293
2016.less.boilerplate.less
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
/*csslint box-model: false, box-sizing: false, universal-selector: false */
|
||||
/*
|
||||
|
||||
|
||||
|
||||
All projects
|
||||
should have nice
|
||||
ASCII ART!
|
||||
|
||||
http://patorjk.com/software/taag/
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@bg: #fff;
|
||||
@fg: #000;
|
||||
|
||||
.transform(@value) {
|
||||
-webkit-transform: @value;
|
||||
-moz-transform: @value;
|
||||
-o-transform: @value;
|
||||
-ms-transform: @value;
|
||||
transform: @value;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Base
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Base
|
||||
|
||||
Normalisering av HTML-element, t ex inmatningsfält, knappar och länkar. Detta
|
||||
avsnitt bör innehålla element- och attributselektorer som är enkla att stila
|
||||
med hjälp av klasser. Klasser ska undvikas.
|
||||
|
||||
Låna så mycket som möjligt från
|
||||
[normalise.css](https://github.com/necolas/normalize.css/blob/master/normalize.css).
|
||||
|
||||
Bastypografin sätts till *large* (ca 24px) med 1.25 radhöjd. Fonten **Open Sans** bäddas in från Google Web Fonts.
|
||||
Fonten ändras med hjälp av media queries (blir mindre på små viewports).
|
||||
|
||||
Markup:
|
||||
Normaliserad text som fyller ut en hel rad genom att
|
||||
fler ord fylls på i det här stycket, även <a href="http://madr.se">länk läggs in</a> för att visa hur den ser ut.
|
||||
<br>Detta är ett hårt radbryt.
|
||||
|
||||
Styleguide 1
|
||||
*/
|
||||
|
||||
*, :before, :after {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
|
||||
background: @bg;
|
||||
color: @fg;
|
||||
font: normal large/1.25 sans-serif;
|
||||
}
|
||||
|
||||
body, ul, p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a[href]:not([class]) {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
button,
|
||||
input[type=submit] {
|
||||
.user-select(text);
|
||||
|
||||
border: 0;
|
||||
font: inherit;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input[type=submit]::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
border: 0;
|
||||
background: #fff;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Template
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Mall
|
||||
|
||||
Innehåller kolumner, ett system för grids och containers fö övriga
|
||||
designkomponenter. Detta avsnitt ska i strikt mening innehålla endast klasser.
|
||||
|
||||
Styleguide 2
|
||||
*/
|
||||
|
||||
/* Float Helpers
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Layouthjälpare (floats)
|
||||
|
||||
Klasser som främst hanterar floats. Är i dagsläget ej anpassade till
|
||||
följsam layout.
|
||||
|
||||
.pull-left - gör ett objekt float: left;
|
||||
.pull-right - gör ett objekt float: right;
|
||||
.line - får en behållare att rymma objekt med floats
|
||||
.clear - får en behållare eller objekt att rensa floats
|
||||
|
||||
Markup:
|
||||
<div class="line">
|
||||
<div class="{$modifiers}">Text</div>
|
||||
</div>
|
||||
|
||||
Styleguide 2.1
|
||||
*/
|
||||
|
||||
.pull-left, .unit {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.line:after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
/* Columns
|
||||
========================================================================== */
|
||||
|
||||
.page {
|
||||
}
|
||||
|
||||
|
||||
/* Grid
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Grid
|
||||
|
||||
Griden är baserad på YUI grids och är i skrivandets stund ej anpassad för
|
||||
följsam layout.
|
||||
|
||||
Markup:
|
||||
<div class="line">
|
||||
<div class="unit size1of2">1/2</div>
|
||||
<div class="unit size1of2">1/2</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="unit size1of3">1/3</div>
|
||||
<div class="unit size2of2">2/3</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="unit size1of4">1/4</div>
|
||||
<div class="unit size3of4">3/4</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="unit size1of5">1/5</div>
|
||||
<div class="unit size4of5">4/5</div>
|
||||
<div class="unit size3of5">3/5</div>
|
||||
<div class="unit size2of5">2/5</div>
|
||||
</div>
|
||||
|
||||
Styleguide 2.2
|
||||
*/
|
||||
|
||||
.unit {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.size1of5 { width: 20% }
|
||||
.size1of4 { width: 25% }
|
||||
.size1of3 { width: 33.3333% }
|
||||
.size2of5 { width: 40% }
|
||||
.size1of2 { width: 50% }
|
||||
.size3of5 { width: 60% }
|
||||
.size2of3 { width: 66.6666% }
|
||||
.size3of4 { width: 75% }
|
||||
.size4of5 { width: 80% }
|
||||
.size1of7 { width: 14.2857% }
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
Core modules
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Kärnmoduler
|
||||
|
||||
Moduler som andra moduler är beroende av för att fungera korrekt, vilket gör
|
||||
att dessa behöver komma först i The Cascade.
|
||||
|
||||
Detta avsnitt ska endast innehålla klasser och media queries, med få undantag.
|
||||
|
||||
Styleguide 3
|
||||
*/
|
||||
|
||||
/* nav pattern */
|
||||
.nav { list-style: none; padding: 0;}
|
||||
.nav a, .nav strong { display: block; }
|
||||
|
||||
|
||||
/* Headings
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Rubriker
|
||||
|
||||
Rubriker används för att skapa sektioner och avdelningar i designen.
|
||||
|
||||
.big - Överdrivet stor rubrik
|
||||
.h1 - Dominant one-of-a-kind rubrik
|
||||
.h2 - typisk sektionsrubrik
|
||||
|
||||
Markup:
|
||||
<div class="{$modifiers}">En rubrik<br>med ett radbryt</div>
|
||||
|
||||
Styleguide 3.2
|
||||
*/
|
||||
|
||||
h1, .h1 {
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
font-size: 1.66em;
|
||||
}
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
Modules
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
Moduler
|
||||
|
||||
Modulerna i detta asvnitt är isolerade och beror ej på andra moduler som ej är
|
||||
kärnmoduler, detta för att enkelt kunna slå av och på CSS. Normalt sett så
|
||||
är modulerna utökningar av kärnmoduler och behållare.
|
||||
|
||||
Avsnittet ska enbart innehålla klasser och media queries, med få undantag.
|
||||
|
||||
Styleguide 4
|
||||
*/
|
||||
|
||||
|
||||
92
2019.python.podcast-downloader.py
Normal file
92
2019.python.podcast-downloader.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
"""
|
||||
Podcast backup script
|
||||
|
||||
Parses an RSS feed from SOURCE_FILE and download all items to
|
||||
DESTINATION_PATH. Downloads are done in parallel, for
|
||||
PARALLEL_COUNT downloads at the time.
|
||||
|
||||
How to use
|
||||
----------
|
||||
|
||||
1. Set DESTINATION_PATH. Make sure the folder exists on your
|
||||
file system.
|
||||
2. Save the source file (RSS or Atom) on your computer and
|
||||
update SOURCE_FILE if needed.
|
||||
3. Alter PARALLEL_COUNT for your needs. Higher number will
|
||||
decrease total time for this script to be done, but will
|
||||
increase net traffic.
|
||||
4. Run script in a python intepreter, 3.7 is recommended.
|
||||
|
||||
This script was written by Anders Ytterström in October 2019.
|
||||
If you find it useful, buy him a 🍺.
|
||||
"""
|
||||
import queue
|
||||
import threading
|
||||
import xml.etree.ElementTree as ET
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
DESTINATION_PATH = "D:\Asmodean\podcasts\inbox"
|
||||
SOURCE_FILE = "D:\Kod\gists\src.xml"
|
||||
PARALLEL_COUNT = 3
|
||||
|
||||
|
||||
def download_file(url, target):
|
||||
print(f"Downloading {target} <- {url}")
|
||||
urlretrieve(url, f"{DESTINATION_PATH}\{target}.mp3")
|
||||
|
||||
|
||||
def get_urls():
|
||||
tree = ET.parse(SOURCE_FILE)
|
||||
root = tree.getroot()
|
||||
|
||||
def f(item):
|
||||
url = item.find("enclosure").attrib["url"]
|
||||
filename = slugify(item.find("title").text)
|
||||
return (url, filename)
|
||||
|
||||
return map(f, root.findall("./channel/item"))
|
||||
|
||||
|
||||
def slugify(text):
|
||||
return (
|
||||
text.lower()
|
||||
.replace(" ", "-")
|
||||
.replace(":", "")
|
||||
.replace("/", "-av-")
|
||||
.replace("?", "")
|
||||
)
|
||||
|
||||
|
||||
def do_work(item):
|
||||
download_file(*item)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
def worker():
|
||||
while True:
|
||||
item = q.get()
|
||||
if item is None:
|
||||
break
|
||||
do_work(item)
|
||||
q.task_done()
|
||||
|
||||
q = queue.Queue()
|
||||
threads = []
|
||||
for i in range(PARALLEL_COUNT):
|
||||
t = threading.Thread(target=worker)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
|
||||
source = get_urls()
|
||||
for item in source:
|
||||
q.put(item)
|
||||
|
||||
# block until all tasks are done
|
||||
q.join()
|
||||
|
||||
# stop workers
|
||||
for i in range(PARALLEL_COUNT):
|
||||
q.put(None)
|
||||
for t in threads:
|
||||
t.join()
|
||||
71
2020.css.shame.css
Normal file
71
2020.css.shame.css
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
acronym,
|
||||
applet,
|
||||
basefont,
|
||||
big,
|
||||
center,
|
||||
dir,
|
||||
font,
|
||||
isindex,
|
||||
menu,
|
||||
noframes,
|
||||
s,
|
||||
strike,
|
||||
tt,
|
||||
u {
|
||||
color: red !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
[rev],
|
||||
[charset],
|
||||
[shape],
|
||||
[coords],
|
||||
[longdesc],
|
||||
link[target]
|
||||
[nohref]
|
||||
img[name]
|
||||
archive object
|
||||
classid object
|
||||
codebase object
|
||||
codetype object
|
||||
declare object
|
||||
standby object
|
||||
valuetype param
|
||||
type param
|
||||
axis td and t
|
||||
abbr td and t
|
||||
scope td
|
||||
align caption, iframe, img, input, object, legend, table, hr, div, h1, h2, h3, h4, h5, h6, p, col, colgroup, tbody, td, tfoot, th, thead and tr.
|
||||
alink body
|
||||
link body
|
||||
vlink body
|
||||
text body
|
||||
background body
|
||||
bgcolor table, tr, td, th and body.
|
||||
border table and object.
|
||||
cellpadding table
|
||||
cellspacing table
|
||||
char col, colgroup, tbody, td, tfoot, th, thead and tr.
|
||||
charoff col, colgroup, tbody, td, tfoot, th, thead and tr.
|
||||
clear br
|
||||
compact dl, menu, ol and ul.
|
||||
frame table
|
||||
compact dl, menu, ol and ul.
|
||||
frame table
|
||||
frameborder iframe
|
||||
hspace img and object.
|
||||
vspace img and object.
|
||||
marginheight iframe
|
||||
marginwidth iframe
|
||||
noshade hr
|
||||
nowrap td and th
|
||||
rules table
|
||||
scrolling iframe
|
||||
size hr
|
||||
type li, ol and ul.
|
||||
valign col, colgroup, tbody, td, tfoot, th, thead and tr
|
||||
width hr, table, td, th, col, colgroup and pre.
|
||||
|
||||
br + br {
|
||||
display: none;
|
||||
}
|
||||
12
2021.spreadsheet.army-fat.txt
Normal file
12
2021.spreadsheet.army-fat.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Males (B2: waist, C2: neck)
|
||||
# Replace `height` with actual height
|
||||
# for the imperial system, replace 30,3 with 36,76
|
||||
=86,01 * Log10(B2 - C2) - 70,041 * log10(height) + 30,3
|
||||
|
||||
# Females (B2: waist, C2: neck, D2: hips)
|
||||
# Replace `height` with actual height
|
||||
# for the imperial system, replace 104,912 with 78,387
|
||||
=163,205 * Log10(B2 + D2 - C2) - 97,684 * Log10(height) - 104,912
|
||||
|
||||
# ALL MEASUREMENTS SHOULD BE DONE IN METRIC, LIKE THE REST OF THE WORLD DOES IT.
|
||||
# https://friendlybit.com/other/im-not-from-america/
|
||||
Loading…
Add table
Reference in a new issue