Rename directory to better suit the moving time.

Kind of also fix the apache conf, but not quite.
This commit is contained in:
2016-08-20 22:39:56 +02:00
parent 95bc653f50
commit ffcf9fefd5
438 changed files with 2 additions and 2 deletions

View File

@@ -0,0 +1,11 @@
This folder holds the JavaScript files used by Algohol. For an understanding of how the JavaScript environment of Algohol works, it's a good idea to read the files in the following order:
1. navbar.js
2. screen.js
3. scr_window.js
4. themes.js
5. onload.js
The 5 files are all commented.
The httpobj.js file found in this directory does not have anything to do with the environment directly, but it's still pretty important. Algohol needs it. The httpobj.js file is not commented.

View File

@@ -0,0 +1,106 @@
/*
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
httpobj: javascript class using XMLHttpRequest to send and retrieve info.
See /httpobj to get an example of the usage.
*/
//v.1.0
function httpobj() {
// Get XMLHttpRequest object
this.obj = this.getobj()
if (!this.obj) {
alert('Your browser does not support HTTP Requests! Get a new one (a browser, that is. Not a request).')
delete this
return false
}
// Define default variables
this.param = {}
this.method = 'POST'
// Fix for later on
this.obj.topelem = this
}
httpobj.prototype.getobj = function() {
// Try to get the XMLHttpRequest object
try { return new XMLHttpRequest() } catch (e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.6.0') } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.3.0') } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP') } catch(e) {}
try { return new ActiveXObject('Microsoft.XMLHTTP') }
catch(e) {
return false // FAILURE
}
}
httpobj.prototype.send = function() {
/*
send(): Sends parametres (param) to url (url) and sets up function to
react on retrievement
*/
if (!this.url) {
// Exit function if either url or the function to be called is undefined
delete this
return false
}
// Transform param into string type ?foo=bar&hmm=aha
this.text_params = ''
if (this.param) {
for (var x in this.param)
this.text_params += '&' + x + '=' + this.param[x]
this.text_params = this.text_params.substr(1)
}
if (this.method.toLowerCase() == 'get') {
// In case of GET method, use '?'
var after_url
if (!this.param)
after_url = ''
else
after_url = '?' + this.text_params
this.obj.open('GET', this.url + after_url, true)
this.obj.send(null)
}
else {
// In case of POST method, use RequestHeader
this.obj.open('POST', this.url, true)
this.obj.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
this.obj.setRequestHeader('Content-length', this.text_params.length)
this.obj.setRequestHeader('Connection', 'close')
this.obj.send(this.text_params)
}
// What to do when something happens
this.obj.onreadystatechange = function() {
// Only do something when it's complete
if (this.readyState == 4 || this.readyState == 'complete') {
// Define 3 variables to be used with the user-defined function (func)
var text, params, state
text = this.responseText
params = this.topelem.param // this.topelem = this.obj.topelem = this
// State 0 is good, state 1 is bad
state = 0
if (this.status != 200) {
state = 1
text = ''
}
// Call user-defined function
if (this.topelem.func)
eval(this.topelem.func)
delete this
}
}
return true // It has a chance of working..
}

View File

@@ -0,0 +1,285 @@
/*
Algo: a dekstop environment look-a-like in your web browser
Copyright (C) 2009 Niels Serup
This file is part of Algo.
Algo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Algo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Algo. If not, see <http://www.gnu.org/licenses/>.
*/
/*
The navbar class creates a navigation bar. Normally Algo features two
navigation bars - one at the top of the page and one at the bottom of the
page. Several obejcts can be added to a navigation bar after its creation,
including dropdowns, appboxes (the boxes with text that you can click on,
usually found in the bottom navigation bar) and a clock. The style of the
navigation bar itself and the objects on the navigation bar is found in an
external css themes file.
*/
function navbar(pos) {
// navnum = the order in which it was created (0, 1, etc.)
this.navnum = navi.length
// If pos is undefined, set the navigation bar to be at the top
if (pos == undefined || pos == -1) var pos = [[0, ''], -1, -1, [0, '']]
// Save pos
this.pos = pos
// Create the actual navigation bar element
this.menu = document.createElement('div')
/* Makes it identifiable by a css file.
By adding " navi" followed by the number of the navbar,
each navbar can be independently changed by a css file */
this.menu.className = 'navbar navi' + this.navnum
// Update the position of the navbar
this.update()
// Append the navbar to the wrapper
wrapper.appendChild(this.menu)
}
navbar.prototype.update = function() {
// Loop through the 4 global directions (top to right)
for (var i = 0; i < global_directions_length; i++) {
/* If the pos is not no-existant, style the navbar's menu element with the
amount ([i][0]) followed by a unit ([i][1]) */
if (this.pos[i] != -1)
this.menu.style[global_directions[i]] = this.pos[i][0] + this.pos[i][1]
}
}
navbar.prototype.support = function(name) {
/* When supporting objects, they will be linked to the supporting navbar
to make them accesible later on via the global "posis" list */
posis[name] = this.navnum
// Special cases
if (name == 'dropdowns')
this.drops = []
}
navbar.prototype.unsupport = function(name) {
// Cease support of a certain object
if (posis[name] == undefined) return
delete posis[name]
// Special cases
if (name == 'dropdowns')
delete this.dropdowns
else if (name == 'appboxes')
delete this.appboxes
}
// DROPDOWN
navbar.prototype.drop = function(name, list) {
/* Adds a dropdown menu. Dropdowns will appear in the order they are created.
"name" is the name of the dropdown menu, while "list" holds all the
entries in an array-like format.
*/
var listlen = list.length
var wrap = this.append_level(list, name)
this.dropdowns.appendChild(wrap)
// Adds a new dropdown object to the "drops"
this.drops[this.drops.length] = [wrap, name, list]
}
navbar.prototype.append_level = function(list, first) {
/* This function creates the elements of a dropdown menu,
based on a list of strings and (eventually) more lists.
This function will call itself if a list at level one
has another list. That way, there are no factors that
limit the number of levels in a dropdown menu. "first"
is set to the name of the list when called from the
original drop prototype function, while it is set to
false when called from this function itself. */
var listlen = list.length
var i, wrap, dtop, type, elem, elema, elemb, spl, title
// Creates the temporary element that will hold everything
wrap = document.createElement('div')
if (first) {
wrap.className = 'dropdown'
// dtop = the header element
dtop = document.createElement('div')
// Adds two classes, one general and one special (" drop" + drops.length)
dtop.className = 'top drop' + navi[posis['dropdowns']].drops.length
dtop.innerHTML = first
wrap.appendChild(dtop)
}
else {
/* If it's not the first time the function is called, it will create a
div with entries instead of a div with a header. */
wrap.className = 'entries'
elem = document.createElement('div')
elem.className = 'side'
wrap.appendChild(elem)
}
/* This is the main loop. It looks at the list entries and evaluates them
based on what they are. If a string is encountered, it is written to the
dropdown menu. If an object (a list in this case) is encountered, this
function is recalled with the sublist as the main list. */
for (i = 0; i < listlen; i++) {
type = typeof(list[i])
if (type == 'string') {
spl = [list[i], 'true']
if (list[i].indexOf('#') != -1)
spl = list[i].split('#')
elem = document.createElement('div')
elem.className = 'entry'
elem.rel = spl[1]
elem.onmouseup = function() {
navi[posis['dropdowns']].hide_drops()
}
elem.innerHTML = spl[0]
elem.onclick = function() {
eval('scr.setwindow(\'' + this.innerHTML + '\',' + this.rel + ')')
}
wrap.appendChild(elem)
}
else if (type == 'object') {
elem = document.createElement('div')
elem.className = 'group'
elema = document.createElement('div')
elema.className = 'header'
elema.innerHTML = list[i][0]
elem.appendChild(elema)
elema = this.append_level(list[i][1])
elem.appendChild(elema)
wrap.appendChild(elem)
}
}
return wrap
}
navbar.prototype.hide_drops = function() {
/* When clicking on an entry in a dropdown menu, the mouse will still hover
the dropdown element, and the dropdown element will still be visible.
By temporarily changing the class of the dropdown menu, this function
makes the dropdown disappear. */
if (!hiding_drops) {
hiding_drops = true
var l = this.drops.length
for (i = 0; i < l; i++) {
this.drops[i][0].className = 'dropdownh dropdown'
}
// No need to wait for more than 0.1 seconds
setTimeout('navi[posis[\'dropdowns\']].hide_drops()', 100)
}
else {
hiding_drops = false
var l = this.drops.length
for (i = 0; i < l; i++) {
this.drops[i][0].className = 'dropdown'
}
}
}
navbar.prototype.box = function(name, pos) {
/* This function adds a box with an object to the navigation bar. "pos" is
the css float property and is completely optional. For the most part it
should in fact not be neccesary to use it, as the styles of most elements
added by this function is defined in a css file. */
if (pos == undefined) pos = 'none'
this[name] = document.createElement('div')
this[name].className = name
this[name].style.cssFloat = pos
this.menu.appendChild(this[name])
// Special cases
if (name == 'clock') {
this.setclock()
this.clockinterval = setInterval('navi[posis[\'clock\']].setclock()', 30000)
}
if (name == 'abs_scroller') {
// abs_scroller appears when there is not enough space for all appboxes.
this.abs_scroller.className = 'abs'
var elem
elem = document.createElement('div')
elem.className = 'scrollup'
elem.onclick = function() {
// Scroll up
navi[posis['appboxes']].abs_scroll(1)
}
this.abs_scroller.appendChild(elem)
elem = document.createElement('div')
elem.className = 'scrolldown'
elem.onclick = function() {
// Scroll down
navi[posis['appboxes']].abs_scroll(-1)
}
this.abs_scroller.appendChild(elem)
this.menu.style.overflow = 'hidden'
}
}
navbar.prototype.check_abs_height = function(force) {
/* This function checks if there is a need for a scroller, i.e. if there are
too many appboxes to be shown in one line. */
var abs = navi[posis['appboxes']].height
var rnum = navi[posis['appboxes']].appboxes.scrollHeight
if (ie) {
// Internet Explorer has some issues. This fix isn't perfect.
if ((rnum / abs + '').indexOf('.') != -1) rnum += appbox_margin * 2
}
var num = rnum / abs
if (num > 1) {
// If there are too many appboxes
navi[posis['appboxes']].appboxes.style.marginRight = abs_scroller_width + 3 + 'px'
navi[posis['appboxes']].abs_scroller.style.display = 'block'
/* If the force is true, scroll to the place where the window linked with
the appbox is */
if (force) this.abs_scroll(-Math.floor(wnds[scr.wndpos[0]].appbox.offsetTop / abs))
}
else {
navi[posis['appboxes']].appboxes.style.marginRight = '0'
navi[posis['appboxes']].abs_scroller.style.display = 'none'
this.abs_scroll(-abs_scrolled)
}
}
navbar.prototype.abs_scroll = function(am) {
var abam = abs_scrolled + am * 1
var abs = this.height
var rnum = this.appboxes.scrollHeight
if (ie) {
// Internet Explorer has some issues. This fix isn't perfect.
if ((rnum / abs + '').indexOf('.') != -1) rnum += appbox_margin * 2
}
/* num = the actual height of the appboxes container divided with the
displayed height */
var num = rnum / abs
if (abs_scrolled + am < 1 && abam * -1 < num) {
// Only do the scrolling if there's something to scroll to
abs_scrolled = abam
this.appboxes.style.marginTop = abs * abs_scrolled + 'px'
}
}
navbar.prototype.setclock = function() {
var time = new Date ()
var hours = time.getHours()
var minutes = time.getMinutes()
// "07" is nicer than just "7"
hours = (hours < 10 ? "0" : "") + hours
minutes = (minutes < 10 ? "0" : "") + minutes
this.clock.innerHTML = hours + ':' + minutes
}

View File

@@ -0,0 +1,166 @@
/*
Algo: a dekstop environment look-a-like in your web browser
Copyright (C) 2009 Niels Serup
This file is part of Algo.
Algo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Algo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Algo. If not, see <http://www.gnu.org/licenses/>.
*/
window.onload = function() {
// Get the head element
head_con = document.getElementsByTagName('head')[0]
// Theme support - .href will be added at the end of the onload function
theme = document.createElement('link')
theme.rel = 'stylesheet'
theme.type = 'text/css'
head_con.appendChild(theme)
// wrapper holds everything
wrapper = document.createElement('div')
wrapper.style.display = 'none'
document.body.appendChild(wrapper)
// A lot of globals used in various functions
global_directions = ['top', 'right', 'bottom', 'left']
global_directions_length = global_directions.length
global_directions_dt = ['tl', 't', 'tr', 'r', 'br', 'b', 'bl', 'l']
global_directions_dt_length = global_directions.length
global_options = ['minimize', 'maximize', 'close']
hiding_drops = false
posis = {}
wnds = new Array()
x = 0
y = 0
moving_window = -1
adjusting_window = -1
adjusting_dir = -1
start_x = -1
start_y = -1
diff_x = 0
diff_y = 0
width_min = 150
height_min = 100
abs_scroller_width = 10
appbox_padding = 2
appbox_margin = 2
appbox_border = 1
abs_scrolled = 0
theme_set = false
// Ew
if (navigator.appName == 'Microsoft Internet Explorer') ie = true
else ie = false
/* Prepares fixing a highligthing problem that occurs whenever
you've moved or adjusted a window. */
highlightfix = document.createElement('textarea')
highlightfix.className = 'highlightfix'
highlightfix.value = 'fix'
wrapper.appendChild(highlightfix)
// Extra security for some elements that just don't exist
fallback = document.createElement('div')
// navi = navigation bar = navbar. Here 2 are created.
navi = []
navi[0] = new navbar([[0, ''], -1, -1, [0, '']])
navi[1] = new navbar([-1, -1, [0, ''], [0, '']])
// Where to put different stuff..
navi[0].support('dropdowns')
navi[0].support('clock')
navi[1].support('appboxes')
// ..and actually putting it there
navi[posis['dropdowns']].box('dropdowns', 'left')
navi[posis['clock']].box('clock')
navi[posis['appboxes']].box('appboxes', 'left')
navi[posis['appboxes']].box('abs_scroller')
/* Create dropdown menus. You can change the way a window opens
by writing a "#" after the title, followed by your variables */
navi[posis['dropdowns']].drop('Programs', [
['Math', [
'Calculator'
]],
['Office', [
'Notes#true,-1,-1,400,400,w-405,sh-405'
]]
])
navi[posis['dropdowns']].drop('Algo', [
'About',
'Help',
])
navi[posis['dropdowns']].drop('Test', [
'A',
['B', [
'C',
'D',
['E', [
['F', [
'G',
'H'
]]
]],
'I'
]]
])
// Create the screen area (the area on which the windows can move freely)
scr = new screen()
scr.wh()
// Event actions
document.onmousemove = scr.set_coor
window.onresize = function() {
scr.update()
for (var i = 0; i < scr.len; i++) {
if (!wnds[i].normal) {
scr.wh()
wnds[i].width = w + scr.margin_g * 2
wnds[i].height = sh + scr.margin_g
wnds[i].update()
}
}
// Check if scrollbars are needed to make all appboxes visible
navi[posis['appboxes']].check_abs_height(false)
}
document.onmouseup = function() {
// End various stuff
if (moving_window > -1)
scr.move_end()
if (adjusting_window > -1)
scr.adjust_end()
}
// Set the theme (will default to the default if you specify an unexisting theme)
settheme('Default')
}

View File

@@ -0,0 +1,407 @@
/*
Algo: a dekstop environment look-a-like in your web browser
Copyright (C) 2009 Niels Serup
This file is part of Algo.
Algo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Algo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Algo. If not, see <http://www.gnu.org/licenses/>.
*/
/*
This is the scr_window class. It takes care of creating windows and
editing windows. When a window has been created, it can be minimized,
maximized and closed by the prototype functions of this class.
*/
function scr_window(title, icon, state, options, width, height, xpos, ypos, resizeable) {
if (title == undefined) return // The title is the identifier - a must
if (icon == undefined) var icon = false // Defaults to no icon
if (state == undefined || state == -1) var state = 1 // 0 = minimized, 1 = normal, 2 = maximized
if (options == undefined || options == -1) var options = [1, 1, 1] // Both minimizable, maximizeable and closeable
if (width == undefined || width == -1) var width = 500 // Default width
if (height == undefined || height == -1) var height = 350 // Default height
if (xpos == undefined || xpos == -1) var xpos = (w - width) / 2 // Places it center
if (ypos == undefined || ypos == -1) var ypos = (sh - height) / 2 // Places it in the middle
if (resizeable == undefined || resizeable == -1) var resizeable = true // Resizable as default
if (width < width_min) width = width_min // Limits
if (height < height_min) height = height_min // Limits
// Uniqueifyes the variables
this.title = title
this.icon = icon
this.options = options
this.width = width
this.height = height
this.resizeable = resizeable
/* Creates two unique numbers. "num" will change if a window opened before
this window is closed, while onum will never change */
this.num = scr.len
this.onum = scr.olen
// Creates the appbox in the appbox navbar
this.appbox = document.createElement('div')
this.appbox.rel = wnds.length // Accesible by JavaScript
this.appbox.onclick = function() {
// Minimize if visible and current
// Change focus if visible but not current
// Unminimize if not visible (the "un"-part happens automatically)
if (wnds[this.rel].visible) {
if (wnds[this.rel].appbox.className == 'current')
wnds[this.rel].minimize(this.rel)
else
scr.change_focus(this.rel)
}
else
wnds[this.rel].minimize(this.rel)
}
this.appbox.innerHTML = title
// Appending it
navi[posis['appboxes']].appboxes.appendChild(this.appbox)
/* The following code creates all the neccesary elements for a window to
exist. It's fairly straight-forward, but it takes up a lot of space */
var elems, belems, el, tmp, i, c
this.elem = document.createElement('div')
this.elem.className = 'window'
el = 13 // The number of elements to be created
if (icon) el++
tmp = 0
if (options[0]) tmp++
if (options[1]) tmp++
if (options[2]) tmp++
this.optboxes = tmp
if (tmp > 0) el++
elems = new Array(el)
belems = new Array(tmp)
// Borders
for (i = 0; i < 8; i++) {
elems[i] = document.createElement('div')
elems[i].className = global_directions_dt[i]
if (i != 1) {
if (resizeable) {
elems[i].rel = i + ''
elems[i].onmousedown = function() {
if (wnds[this.parentNode.rel].normal)
scr.adjust_start(this.parentNode.rel, this.rel)
}
elems[i].onmouseup = function() {
scr.adjust_end()
}
}
}
}
// Title + text + icon + options
elems[8] = document.createElement('div')
elems[8].className = 'title'
elems[8].innerHTML = this.title
elems[9] = document.createElement('div')
elems[9].className = 'handle'
elems[9].onmousedown = function() {
if (wnds[this.parentNode.rel * 1].normal) {
scr.move_start(this.parentNode.rel * 1)
}
}
elems[9].onmouseup = function() {
scr.move_end()
}
elems[9].ondblclick = function() {
wnds[this.parentNode.rel * 1].maximize()
}
elems[10] = document.createElement('div')
elems[10].className = 'resize_handle'
if (resizeable) {
elems[10].rel = '1'
elems[10].onmousedown = function() {
if (wnds[this.parentNode.rel * 1].normal)
scr.adjust_start(this.parentNode.rel * 1, this.rel * 1)
}
elems[10].onmouseup = function() {
scr.adjust_end()
}
}
else
this.elem.className += ' nrsz' // Seen by a css file
if (!ie) {
elems[11] = document.createElement('object')
elems[11].data = 'pages/links.php?title=' + escape(title) + '&num=' + this.onum
elems[11].type = 'text/html'
}
else {
elems[11] = document.createElement('iframe')
elems[11].src = 'pages/links.php?title=' + escape(title) + '&num=' + this.onum
elems[11].frameBorder = '0'
}
elems[11].className = 'data'
elems[12] = document.createElement('div')
elems[12].className = 'data_overlay'
if (icon) {
elems[13] = document.createElement('div')
elems[13].className = 'icon'
elems[13].style.backgroundImage = 'url(\'pages/links.php?title=' + escape(title) + '&type=png\')'
}
if (this.optboxes > 0) {
// If any options at all
tmp = elems.length - 1
elems[tmp] = document.createElement('div')
elems[tmp].className ='options'
c = 0
for (i = 0; i < 3; i++) {
if (options[i]) {
belems[i] = document.createElement('div')
belems[i].className = global_options[i] // Refer to onload.js
if (global_options[i] == 'minimize') belems[i].onclick = function() {
wnds[this.parentNode.parentNode.rel * 1].minimize()
}
else if (global_options[i] == 'maximize') belems[i].onclick = function() {
wnds[this.parentNode.parentNode.rel * 1].maximize()
}
else belems[i].onclick = function() {
wnds[this.parentNode.parentNode.rel * 1].close()
}
elems[tmp].appendChild(belems[i])
c++
}
}
}
// All clickable elements need elem.rel to determine what window to change
this.elem.rel = wnds.length
this.elem.onmousedown = function() {
scr.change_focus(this.rel * 1)
}
this.elem.style.left= xpos + 'px'
this.elem.style.top = ypos + 'px'
for (i = 0; i < el; i++) {
// Append all created elements
this.elem.appendChild(elems[i])
}
this.len = this.elem.childNodes.length
scr.elem.appendChild(this.elem)
this.visible = true
this.normal = true
if (state == 0) this.minimize()
this.update() // Adjust widths, heights, etc.
this.update_appbox() // The same with the appbox
if (state == 2) this.maximize()
}
scr_window.prototype.update = function() {
/* This function updates the dimensions of the subelements of a window.
scr holds standard information such as the general margin, while the
window itself has some info about width, height, icons, etc. */
var tmp, el
el = this.cn('tl')
el.style.width = scr.margin_g + 'px' // margin_g is the general margin
el.style.height = scr.hheight + 'px' // hheight is the header height
el = this.cn('t')
el.style.left = scr.margin_g + 'px'
el.style.width = this.width - scr.margin_g * 2 + 'px'
el.style.height = scr.hheight + 'px'
el = this.cn('tr')
el.style.left = this.width - scr.margin_g + 'px'
el.style.width = scr.margin_g + 'px'
el.style.height = scr.hheight + 'px'
el = this.cn('r')
el.style.top = scr.hheight + 'px'
el.style.left = this.width - scr.margin_g + 'px'
el.style.width = scr.margin_g + 'px'
el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
el = this.cn('br')
el.style.top = this.height - scr.margin_g + 'px'
el.style.left = this.width - scr.margin_g + 'px'
el.style.width = scr.margin_g + 'px'
el.style.height = scr.margin_g + 'px'
el = this.cn('b')
el.style.top = this.height - scr.margin_g + 'px'
el.style.left = scr.margin_g + 'px'
el.style.width = this.width - scr.margin_g * 2 + 'px'
el.style.height = scr.margin_g + 'px'
el = this.cn('bl')
el.style.top = this.height - scr.margin_g + 'px'
el.style.width = scr.margin_g + 'px'
el.style.height = scr.margin_g + 'px'
el = this.cn('l')
el.style.top = scr.hheight + 'px'
el.style.width = scr.margin_g + 'px'
el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
el = this.cn('title')
el.style.top = scr.margin_g + 'px'
el.style.height = scr.hheight - scr.margin_g + 'px'
if (this.icon) tmp = scr.bw + scr.margin_t
else tmp = 0
el.style.left = scr.margin_g + scr.margin_t + tmp + 'px'
el.style.width = this.width - scr.margin_g * 2 - scr.margin_t * 2 - this.optboxes * (scr.bw + scr.margin_t) - tmp + 'px'
el = this.cn('handle')
el.style.top = scr.margin_g + 'px'
el.style.height = scr.hheight - scr.margin_g + 'px'
el.style.left = scr.margin_g + scr.bw + scr.margin_t + 'px'
el.style.width = this.width - scr.margin_g * 2 - this.optboxes * (scr.bw + scr.margin_t) - tmp + 'px'
el = this.cn('resize_handle')
el.style.left = scr.margin_g + 'px'
el.style.width = this.width - scr.margin_g * 2 + 'px'
el.style.height = scr.margin_g + 'px'
el = this.cn('data')
el.style.top = scr.hheight + 'px'
el.style.left = scr.margin_g + 'px'
el.style.width = this.width - scr.margin_g * 2 + 'px'
el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
el = this.cn('data_overlay')
el.style.top = scr.hheight + 'px'
el.style.left = scr.margin_g + 'px'
el.style.width = this.width - scr.margin_g * 2 + 'px'
el.style.height = this.height - scr.hheight - scr.margin_g + 'px'
if (this.icon) {
el = this.cn('icon')
el.style.top = scr.margin_g + 'px'
el.style.left = scr.margin_g + scr.margin_t + 'px'
el.style.width = scr.bw + 'px' // bw is the box width
el.style.height = scr.bh + 'px' // bh is the box height
}
el = this.cn('options')
if (el) {
el.style.top = scr.margin_g + 'px'
el.style.left = this.width - this.optboxes * (scr.bw + scr.margin_t) - scr.margin_g + 'px'
el.style.width = this.optboxes * (scr.bw + scr.margin_t) - scr.margin_t + 'px' // margin_t is the margin used in the top of the window
el.style.height = scr.bh + 'px'
var elc = el.childNodes
var elcl = elc.length
for (var i = 0; i < elcl; i++) {
elc[i].style.left = i * (scr.bw + scr.margin_t) + 'px'
elc[i].style.width = scr.bw + 'px'
}
}
}
scr_window.prototype.update_appbox = function() {
this.appbox.style.height = navi[posis['appboxes']].height - appbox_padding * 2 - appbox_margin * 2 - appbox_border * 2 + 'px'
}
scr_window.prototype.cn = function(what) {
/* This function is a smart one. It returns a pointer to the node which
has the class specified by "what". If it's not found, the returned node
is "fallback", which does nothing but at the same time makes sure no
errors pop up. */
var i = 0
var ok = false
var nodes = this.elem.childNodes
var node = fallback
while (i < this.len && !ok) {
if (nodes[i].className == what) {
node = nodes[i]
ok = true
}
i++
}
return node
}
scr_window.prototype.settitle = function(title) {
// Sets the title of the window and the appbox associated with the window
this.cn('title').innerHTML = title
this.appbox.innerHTML = title
}
scr_window.prototype.minimize = function() {
/*
Minimizes if visible
Unminimizes if not visible
*/
if (this.visible) {
this.visible = false
this.elem.style.display = 'none'
scr.change_focus(this.num, 1)
}
else {
this.visible = true
this.elem.style.display = 'block'
scr.change_focus(this.num)
}
}
scr_window.prototype.maximize = function() {
/*
Maximizes if normal
Unmaximizes if already maximized
*/
if (this.normal) {
this.normal = false
this.savedpos = [this.elem.offsetLeft, this.elem.offsetTop, this.width, this.height]
this.elem.style.left = -scr.margin_g + 'px'
this.elem.style.top = 0
this.width = w + scr.margin_g * 2
this.height = sh + scr.margin_g
this.elem.className = 'window window_max'
}
else {
this.normal = true
this.elem.style.left = this.savedpos[0] + 'px'
this.elem.style.top = this.savedpos[1] + 'px'
this.width = this.savedpos[2]
this.height = this.savedpos[3]
this.elem.className = 'window'
if (!this.resizeable) this.elem.className += ' nrsz'
}
this.update()
}
scr_window.prototype.close = function() {
// Changes focus with det set to 2, which in turn removes the element
scr.change_focus(this.num, 2)
}
scr_window.prototype.renum = function(n) {
/* This function changes the "num" variable and the attributes that use it.
The "num" variable will in some cases have to be changed when a window
closes. */
this.num += n
this.elem.rel = this.num
this.appbox.rel = this.num
}

View File

@@ -0,0 +1,365 @@
/*
Algo: a dekstop environment look-a-like in your web browser
Copyright (C) 2009 Niels Serup
This file is part of Algo.
Algo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Algo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Algo. If not, see <http://www.gnu.org/licenses/>.
*/
/*
The screen class creates the screen on which all the windows appear.
As a matter of fact, the screen class simply serves as a layer for adding
windows. That's all. */
function screen() {
this.elem = document.createElement('div')
this.elem.className = 'area'
this.elem.style.width = '100%' // Height determined by JavaScript later on
wrapper.appendChild(this.elem)
/* len and olen dynamically increases as new windows are opened. But while
len is decreased when windows are closed, olen is never decreases. This
proves helpful when the windows in objects/iframes must be able to access
their own windows. */
this.len = 0
this.olen = 0
/* wndpos holds information about the windows on the screen. Each wndpos
entry is a link to a scr_window class. wndpos keeps the links in their
index order. */
this.wndpos = new Array()
/* It is neccessary to create an overlay, as the window objects/iframes will
catch focus if the mouse is moved over them. The overlay is on whenever a
window is being moved or adjusted */
this.overlay = document.createElement('div')
this.overlay.className = 'overlay'
this.elem.appendChild(this.overlay)
}
screen.prototype.rethink = function() {
// rethink() reorganises the screen top and height based on the navbars.
var navil = navi.length
var mh, th, borders, bl, border
mh = 0
th = 0
/* The following loop uses the height and the border height of the navbars
to compute the space on which the screen should be positioned. */
for (var i = 0; i < navil; i++) {
border = 0
borders = navi[i].border
bl = borders.length
for (var ii = 0; ii < bl; ii += 2) {
border += borders[ii]
}
mh += navi[i].height
if (navi[i].pos[0] != -1)
th += navi[i].height + border
if (navi[i].pos[0] != -1 || navi[i].pos[2] != -1)
mh += border
}
// bi = the heights of the navbars plus the border heights of the navbars
this.bi = mh
this.elem.style.top = th + 'px'
}
screen.prototype.update = function() {
// Updates width and height and adjusts the height
this.wh()
this.elem.style.height = sh + 'px'
}
screen.prototype.wh = function() {
// Get screen width and height
if (self.innerHeight) {
h = self.innerHeight
w = self.innerWidth
}
else if (document.documentElement && document.documentElement.clientHeight) {
h = document.documentElement.clientHeight
w = document.documentElement.clientWidth
}
else if (document.body) {
h = document.body.clientHeight
w = document.body.clientWidth
}
// sh = screen height - navbars heights. The height of the screen area is sh
sh = h - this.bi
}
screen.prototype.change_focus = function(num, det) {
/* This function changes focus to the window specified in "num". "det" is a
special identifier that tells this function what to do. Or whatever. */
if (det == undefined) var det = 0
var num = num * 1
for (var i = 0; i < this.len; i++) {
// Delete link from the wndpos list
if (this.wndpos[i] == num) this.wndpos.splice(i, 1)
}
/*
if det == 0: add window to front
if det == 1: add window to back
if det == 2: remove and close window
*/
if (det == 0)
this.wndpos.splice(0, 0, num)
else if (det == 1)
this.wndpos.splice(this.len, this.len, num)
else if (det == 2) {
this.len--
this.elem.removeChild(wnds[num].elem)
navi[posis['appboxes']].appboxes.removeChild(wnds[num].appbox)
for (i = 0; i < this.len; i++) {
if (this.wndpos[i] > num) {
wnds[this.wndpos[i]].renum(-1) // Readjust windows with a higher index
this.wndpos[i]--
}
}
// Different actions based on different variables
if (moving_window > num) moving_window--
else if (moving_window == num) this.move_end()
if (adjusting_window > num) adjusting_window--
else if (adjusting_window == num) this.adjust_end()
delete wnds[num]
wnds.splice(num, 1)
}
// This function has no done anything visually. setindex takes care of that.
this.setindex()
}
screen.prototype.setindex = function() {
/* This function writes any changes made in the classes in the wndpos to the
screen. If focus has changed from one window to another, setindex makes
the user see that. */
for (var i = 1; i < this.len; i++) {
wnds[this.wndpos[i]].elem.style.zIndex = this.len - i + 1
wnds[this.wndpos[i]].elem.id = ''
wnds[this.wndpos[i]].appbox.className = ''
}
if (this.len > 0) {
// The first window in the hierarchy gets the focus
wnds[this.wndpos[0]].elem.style.zIndex = this.len + 2
wnds[this.wndpos[0]].elem.id = 'active'
wnds[this.wndpos[0]].appbox.className = ''
this.overlay.style.zIndex = this.len + 1
}
// vis will turn true if any window is visible
var vis = false
for (i = 0; i < this.len; i++) {
if (wnds[i].visible) vis = true
}
// Only make the current window current if at least one window is visible
if (vis) wnds[this.wndpos[0]].appbox.className = 'current'
// Check if there's enough space for the appboxes
navi[posis['appboxes']].check_abs_height(true)
}
screen.prototype.set_overlay = function() {
this.overlay.style.display = 'block'
}
screen.prototype.del_overlay = function() {
this.overlay.style.display = 'none'
}
screen.prototype.move_start = function(what) {
/* "move_start" sets the global value "moving_window" to the active window
and thereby makes it recognisable by the set_coor function. */
moving_window = what * 1
/* The overlays are needed to keep the objects/iframes from getting the
mouse focus. In theory this should not happen, but as the mouse is often
moved faster than the window, this happens.
There are two overlays: one that covers the window and on that covers the
other windows. */
wnds[moving_window].cn('data_overlay').style.display = 'block'
this.set_overlay()
// These are needed later on to determine the position of the window.
diff_x = x - wnds[moving_window].elem.offsetLeft
diff_y = y - wnds[moving_window].elem.offsetTop
}
screen.prototype.move_end = function() {
if (moving_window > -1)
wnds[moving_window].cn('data_overlay').style.display = 'none'
moving_window = -1
this.blurfocus()
}
screen.prototype.adjust_start = function(what, dir) {
/* This is the same as "move_start" except that this does not start moving
the window, but instead it starts adjusting (resizing) it. */
adjusting_window = what * 1
adjusting_dir = dir * 1
wnds[adjusting_window].cn('data_overlay').style.display = 'block'
this.set_overlay()
// Different variables are set depending on the direction of the adjusting.
/*
The directions are:
0: top-left
1: top
2: top-right
3: right
4: bottom-right
5: bottom
6: bottom-left
7: left
If the resize direction is diagonal, both of the below options are true.
*/
if (adjusting_dir != 1 && adjusting_dir != 5) {
// If vertical
start_x = x
start_w = wnds[adjusting_window].width
diff_x = start_x - wnds[adjusting_window].elem.offsetLeft
}
if (adjusting_dir != 3 && adjusting_dir != 7) {
// If horizontal
start_y = y
start_h = wnds[adjusting_window].height
diff_y = start_y - wnds[adjusting_window].elem.offsetTop
}
}
screen.prototype.adjust_end = function() {
if (adjusting_window > -1)
wnds[adjusting_window].cn('data_overlay').style.display = 'none'
adjusting_window = -1
adjusting_dir = -1
this.blurfocus()
}
screen.prototype.blurfocus = function() {
// Hides the overlay and applies the fix
this.del_overlay()
highlightfix.focus()
highlightfix.select()
}
screen.prototype.setwindow = function(a, b, c, d, e, f, g, h, i, j, k, l, m, n) {
// This function is the one that must be called when creating a new window.
wnds[wnds.length] = new scr_window(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
// Positions itself at the front
this.wndpos.splice(0, 0, this.len)
this.len++
this.olen++
this.setindex()
}
screen.prototype.move_window = function() {
// Moves the window based on current and earlier set variables
var cx = x - diff_x
if (cx < -diff_x) cx = -diff_x
else if (cx > w - diff_x) cx = w - diff_x
var cy = y - diff_y
if (cy < 0) cy = 0
else if (cy > sh - scr.hheight) cy = sh - scr.hheight
if (scr.len > moving_window) {
wnds[moving_window].elem.style.left = cx + 'px'
wnds[moving_window].elem.style.top = cy + 'px'
}
}
screen.prototype.adjust_window = function() {
// Adjusts the window based on current and earlier set variables
// This function uses the same direction principle as "adjust_start".
if (adjusting_dir != 1 && adjusting_dir != 5) {
var cx, cw, cxs
cxs = false
if (adjusting_dir == 0 || adjusting_dir == 6 || adjusting_dir == 7) {
// If to the left
cx = x - diff_x
cw = start_w + start_x - x
if (x - diff_x < 0) {
cx = 0
cxs = true
}
}
else {
// If to the right
cx = start_x - start_w + start_w - diff_x
cw = start_w + x - start_x
if (x + start_w - diff_x > w) cxs = true
}
if (cw < width_min) cxs = true
if (!cxs && scr.len > adjusting_window) {
wnds[adjusting_window].elem.style.left = cx + 'px'
wnds[adjusting_window].width = cw
}
}
if (adjusting_dir != 3 && adjusting_dir != 7) {
var cy, ch, cys
cys = false
if (adjusting_dir == 0 || adjusting_dir == 1 || adjusting_dir == 2) {
// If upwards
cy = y - diff_y
ch = start_h + start_y - y
if (y - diff_y < 0) {
cy = 0
cys = true
}
}
else {
// If downwards
cy = start_y - start_y + start_y - diff_y
ch = start_h + y - start_y
if (y + start_h - diff_y > sh) cys = true
}
if (ch < height_min) cys = true
if (!cys && scr.len > adjusting_window) {
wnds[adjusting_window].elem.style.top = cy + 'px'
wnds[adjusting_window].height = ch
}
}
// Update the window position
wnds[adjusting_window].update()
}
screen.prototype.set_coor = function(e) {
/* This function sets the global coordinates of the screen. If a window
is eiher being moved or adjusted, this function calls the "move_window"
or "adjust_window" functions */
if (!e) var e = window.event
if (e.pageX || e.pageY) {
x = e.pageX
y = e.pageY
}
else if (e.clientX || e.clientY) {
x = e.clientX + document.body.scrollLeft
y = e.clientY + document.body.scrollTop
}
if (moving_window != -1)
scr.move_window()
else if (adjusting_window != -1)
scr.adjust_window()
}

View File

@@ -0,0 +1,66 @@
/*
Algo: a dekstop environment look-a-like in your web browser
Copyright (C) 2009 Niels Serup
This file is part of Algo.
Algo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Algo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Algo. If not, see <http://www.gnu.org/licenses/>.
*/
/*
This is the themes file. The two functions in this file manage loading
themes and changing object properties
*/
function settheme(what) {
/* Sets the url of the themes css file. In this case it links to a PHP file
that has an index of names and urls. */
theme.href = 'themes/links.php?title=' + what + '&type=css' + '&r=' + Math.random()
var http = new httpobj() // Creates a new httpobj object
http.url = 'themes/links.php' // Sets the url
http.method = 'get' // Sets the method
http.param['title'] = what // Sets the title
http.param['type'] = 'js' // Sets the type
http.param['r'] = Math.random() // Fix for i.e. IE (maybe other browsers too)
http.func = "themevars(text)" // Will pass received text to that function
http.send() // Sends it
}
function themevars(vars) {
// This function updates everything possible updating.
eval(vars) // Execute the string
for (var i = 0; i < navi.length; i++) {
navi[i].update()
}
// Reshow everything
scr.rethink()
scr.update()
for (var i = 0; i < scr.len; i++) {
wnds[i].update()
wnds[i].update_appbox()
}
// Some browsers are a bit slow, so waiting half a second or so is smart.
setTimeout("wrapper.style.display = 'block'", 500)
setTimeout("navi[posis['appboxes']].check_abs_height(false)", 1000)
if (!theme_set) {
theme_set = true
// Open a small welcome window
setTimeout("scr.setwindow('Welcome', true, -1, -1, 300, 200)", 1000)
}
}