Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
renderjs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
renderjs
Commits
8a1e595d
Commit
8a1e595d
authored
Jun 07, 2013
by
Sven Franck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
reworked 2nd instance in example to only using ajax links
parent
77fdb96b
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
695 additions
and
319 deletions
+695
-319
gadget/filebrowser.js
gadget/filebrowser.js
+95
-64
gadget/filebrowser_and_preview.js
gadget/filebrowser_and_preview.js
+119
-46
gadget/filecontent.js
gadget/filecontent.js
+53
-101
gadget/preview.html
gadget/preview.html
+18
-0
gadget/preview.js
gadget/preview.js
+88
-0
gadget/preview_by_hash_change.js
gadget/preview_by_hash_change.js
+4
-0
gadget/preview_by_postmessage.js
gadget/preview_by_postmessage.js
+65
-45
renderjs.js
renderjs.js
+253
-63
No files found.
gadget/filebrowser.js
View file @
8a1e595d
/*global document, jQuery */
// filebrowser.html?file=browser%3A%2F%2Fbrowse%2Fls%2F
"
use strict
"
;
(
function
(
document
,
$
)
{
"
use strict
"
;
var
getParameter
=
function
(
searchString
,
paramName
)
{
var
i
,
val
,
params
=
searchString
.
split
(
"
&
"
);
...
...
@@ -15,76 +14,108 @@
return
null
;
};
var
mapUrl
=
function
(
url
)
{
var
searchString
=
url
.
href
.
split
(
"
?
"
)[
1
],
fileToDisplay
;
var
mapUrl
=
function
(
searchString
)
{
var
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
),
scope
,
register
,
service
;
if
(
searchString
)
{
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
);
if
(
fileToDisplay
)
{
if
(
fileToDisplay
)
{
$
.
ajax
({
method
:
'
GET
'
,
url
:
fileToDisplay
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
$
.
ajax
({
method
:
'
GET
'
,
// XXX Hardcoded
url
:
fileToDisplay
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
$
.
ajax
({
method
:
'
GET
'
,
// XXX Hardcoded
url
:
value
.
_links
.
storage
.
href
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value2
,
textStatus
,
jqXHR
)
{
var
content_type
=
jqXHR
.
getResponseHeader
(
"
Content-Type
"
)
||
""
;
// XXX Hardcoded mime type
if
(
content_type
.
split
(
'
;
'
)[
0
]
===
"
application/hal+json
"
)
{
// XXX Will fail if response does not send expected links...
$
(
this
).
html
(
"
<ul>
"
);
for
(
var
i
in
value2
.
_links
.
contents
){
$
(
this
).
append
(
"
<li><button id='
"
+
i
+
"
'>
"
+
value2
.
_links
.
contents
[
i
].
href
+
"
</button></li>
"
);
$
(
this
).
find
(
"
#
"
+
i
.
toString
()).
on
(
'
click
'
,
function
(
e
,
target
)
{
$
.
ajax
({
// XXX Hardcoded post and url
// Why using postMessage?
method
:
"
POST
"
,
url
:
value
.
_links
.
display
.
href
,
context
:
$
(
this
),
data
:
$
(
this
).
text
(),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
Plumbing failed:
"
+
errorThrown
);
},
// success: function (value, textStatus, jqXHR) {
// console.log(value);
// },
});
});
}
$
(
this
).
append
(
"
</ul>
"
);
}
else
{
$
(
this
).
text
(
"
Unsupported content type
"
+
content_type
);
};
},
});
},
});
scope
=
value
.
_links
.
scope
.
href
.
slice
(
0
,
-
1
).
split
(
/
[/]
+/
).
pop
();
register
=
value
.
_links
.
call
.
href
.
replace
(
"
{method}
"
,
"
register
"
)
.
replace
(
"
{scope}
"
,
scope
)
.
replace
(
"
{interaction}
"
,
""
);
service
=
{
"
type
"
:
"
service/test
"
,
"
src
"
:
encodeURIComponent
(
window
.
location
.
href
),
"
rel
"
:
"
browse
"
,
"
self
"
:
window
.
frameElement
.
id
};
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
$
.
ajax
({
method
:
'
POST
'
,
url
:
register
,
context
:
$
(
this
),
data
:
JSON
.
stringify
(
service
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
registration failed:
"
+
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
// console.log("registration successful");
}
});
// HACK: this is hacking the functionality provided by the
// filebrowser!
// 'browser://call/browse/' should be called by the interactor
// instead of hardcoding it here
$
.
ajax
({
method
:
'
GET
'
,
url
:
value
.
_links
.
scope
.
href
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value2
,
textStatus
,
jqXHR
)
{
var
content_type
=
jqXHR
.
getResponseHeader
(
"
Content-Type
"
)
||
""
,
request
=
value
.
_links
.
call
.
href
.
replace
(
"
{method}
"
,
"
service
"
)
.
replace
(
"
{scope}
"
,
scope
)
.
replace
(
"
{interaction}
"
,
"
preview
"
);
// XXX Hardcoded mime type
if
(
content_type
.
split
(
'
;
'
)[
0
]
===
"
application/hal+json
"
)
{
// XXX Will fail if response does not send expected links...
$
(
this
).
html
(
"
<ul>
"
);
for
(
var
i
in
value2
.
_links
.
contents
){
$
(
this
).
append
(
"
<li><button id='
"
+
i
+
"
'>
"
+
value2
.
_links
.
contents
[
i
].
href
+
"
</button></li>
"
);
$
(
this
).
find
(
"
#
"
+
i
.
toString
()).
on
(
'
click
'
,
function
(
e
,
target
)
{
$
.
ajax
({
method
:
"
POST
"
,
url
:
request
,
context
:
$
(
this
),
data
:
$
(
this
).
text
(),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
request failed:
"
+
errorThrown
);
},
// success: function (value, textStatus, jqXHR) {
// console.log("request sent");
// }
});
});
}
$
(
this
).
append
(
"
</ul>
"
);
}
else
{
$
(
this
).
text
(
"
Unsupported content type
"
+
content_type
);
};
}
});
},
});
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
(2)
"
);
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
};
$
(
document
).
ready
(
function
()
{
mapUrl
(
window
.
location
);
var
search
=
window
.
location
.
search
;
if
(
search
)
{
mapUrl
(
search
.
slice
(
1
));
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
});
}(
document
,
jQuery
));
gadget/filebrowser_and_preview.js
View file @
8a1e595d
/*global document, jQuery */
// filebrowser.html?file=browser%3A%2F%2Fbrowse%2Fls%2F
"
use strict
"
;
(
function
(
document
,
$
)
{
...
...
@@ -20,6 +19,20 @@
return
-
1
;
};
var
generateUuid
=
function
()
{
var
S4
=
function
()
{
/* 65536 */
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
"
0
"
+
string
;
}
return
string
;
};
return
S4
()
+
S4
();
};
var
getParameter
=
function
(
searchString
,
paramName
)
{
var
i
,
val
,
params
=
searchString
.
split
(
"
&
"
);
...
...
@@ -32,29 +45,69 @@
return
null
;
};
// this is our "interactor", it only knows one other iFrame
// so we post to this one!
var
handler
=
function
(
event
)
{
var
frames
=
document
.
getElementsByTagName
(
"
iframe
"
),
frame
,
i
;
for
(
i
=
0
;
i
<
frames
.
length
;
i
+=
1
)
{
frame
=
frames
[
i
];
if
(
myIndexOf
(
event
.
source
.
location
.
pathname
,
frame
.
getAttribute
(
"
src
"
).
split
(
"
?
"
)[
0
]
)
<
0
)
{
frame
.
contentWindow
.
postMessage
(
event
.
data
,
"
*
"
);
// frame.contentWindow.postMessage(event.data, window.location.href);
}
// prevent registrations to renderJs from triggering here
var
type
=
event
.
data
.
type
,
service
,
scope
,
request
;
if
(
type
===
undefined
)
{
$
.
ajax
({
method
:
"
GET
"
,
url
:
event
.
data
,
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
request failed:
"
+
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
// we now have the URL to handle and the method
// to request. We need to POST this, because
// we can't access renderJS.gadgetService from here...
// when optimizing all the secondary ajax calls should be removed
// question also is, whether we need POST at all, if we could
// pass everything through the URL?
scope
=
value
.
_links
.
self
.
href
.
split
(
"
/
"
).
slice
(
0
,
-
1
).
pop
();
service
=
{
"
service
"
:
value
.
_links
.
self
.
href
.
split
(
/
[/]
+/
).
pop
(),
"
parameters
"
:
[
value
.
_links
.
request
.
href
],
"
scope
"
:
scope
}
request
=
'
browser://request/
'
+
scope
+
'
/
'
;
$
.
ajax
({
method
:
"
POST
"
,
url
:
request
,
context
:
$
(
this
),
data
:
JSON
.
stringify
(
service
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
request for service failed
"
);
},
// success: function () {
// console.log("service requested from renderJS");
// }
});
}
});
// var frames = document.getElementsByTagName("iframe"), frame, i;
// for (i = 0; i < frames.length; i += 1) {
// frame = frames[i];
// if (myIndexOf(
// event.source.location.pathname,
// frame.getAttribute("src").split("?")[0]
// ) < 0) {
// frame.contentWindow.postMessage(event.data, "*");
// }
// }
}
};
var
mapUrl
=
function
(
url
)
{
var
searchString
=
url
.
href
.
split
(
"
?
"
)[
1
],
fileToDisplay
,
fileToDisplayData
;
if
(
searchString
)
{
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
);
var
mapUrl
=
function
(
searchString
)
{
var
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
),
browserAPI
,
previewAPI
;
if
(
fileToDisplay
)
{
$
.
ajax
({
method
:
'
GET
'
,
// XXX Hardcoded
...
...
@@ -64,45 +117,65 @@
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
fileToDisplayData
=
"
data://application/hal+json;base64,
"
+
var
access
;
// detour to request, while working on the 2nd preview window
if
(
value
.
_links
.
target
.
href
===
"
preview_by_postmessage.html
"
)
{
access
=
"
request
"
;
}
else
{
access
=
"
plumb
"
;
}
// merge again once working!
browserAPI
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
value
.
_links
.
storage
.
href
},
storage
:
{
href
:
value
.
_links
.
storage
.
href
},
display
:
{
href
:
'
browser://plumb/parentwindow/
'
},
self
:
{
href
:
value
.
_links
.
scope
.
href
},
scope
:
{
href
:
value
.
_links
.
scope
.
href
},
display
:
{
href
:
'
browser://
'
+
access
+
'
/parentwindow/
'
},
// pass API-url so child can call parent
call
:
{
href
:
'
browser://call/{method}/{scope}/{interaction}
'
}
}}));
if
(
fileToDisplay
)
{
$
(
"
body
"
).
html
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
'
filebrowser.html?file=
'
+
fileToDisplayData
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
previewAPI
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
''
},
scope
:
{
href
:
value
.
_links
.
scope
.
href
},
display
:
{
href
:
''
},
call
:
{
href
:
'
browser://call/{method}/{scope}/{interaction}
'
}
}}));
$
(
"
body
"
).
append
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
value
.
_links
.
preview
.
href
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
$
(
"
body
"
).
html
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
'
filebrowser.html?file=
'
+
browserAPI
+
'
" id="
'
+
generateUuid
()
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
},
$
(
"
body
"
).
append
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
value
.
_links
.
target
.
href
+
'
?file=
'
+
previewAPI
+
'
" id="
'
+
generateUuid
()
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
}
});
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
(2)
"
);
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
};
$
(
document
).
ready
(
function
()
{
mapUrl
(
window
.
location
);
var
search
=
window
.
location
.
search
;
if
(
search
)
{
mapUrl
(
search
.
slice
(
1
));
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
if
(
window
.
addEventListener
){
window
.
addEventListener
(
"
message
"
,
handler
,
false
)
...
...
gadget/filecontent.js
View file @
8a1e595d
/*global document, jQuery */
// filebrowser.html?file=browser%3A%2F%2Fbrowse%2Fls%2F
// filebrowser_and_preview.html?file=browser%3A%2F%2Fbrowse%2Fls%2F
"
use strict
"
;
(
function
(
document
,
$
)
{
// sample contents
localStorage
.
setItem
(
"
foo
"
,
"
bar
"
);
localStorage
.
setItem
(
"
baz
"
,
"
bam
"
);
sessionStorage
.
setItem
(
"
cous
"
,
"
cous
"
);
sessionStorage
.
setItem
(
"
schnick
"
,
"
schnack
"
);
// contents
localStorage
.
setItem
(
"
foo
"
,
"
bar
"
);
localStorage
.
setItem
(
"
baz
"
,
"
bam
"
);
sessionStorage
.
setItem
(
"
cous
"
,
"
cous
"
);
sessionStorage
.
setItem
(
"
schnick
"
,
"
schnack
"
);
// var myIndexOf = function (path, contains) {
// var len = path.length;
// var wordLen = contains.length;
// for(var i = 0; i < len; i++) {
// var j = 0;
// for(j = 0; j < wordLen; j++) {
// if(path[i+j] != contains[j]) {
// break;
// }
// }
// if(j == wordLen) {
// return i;
// }
// }
// return -1;
// };
//
// var getParameter = function(searchString, paramName) {
// var i, val, params = searchString.split("&");
//
// for (i=0;i<params.length;i++) {
// val = params[i].split("=");
// if (val[0] == paramName) {
// return decodeURIComponent(val[1]);
// }
// }
// return null;
// };
//
// // this is our "interactor", it only knows one other iFrame
// // so we post to this one!
// var handler = function (event) {
// var frames = document.getElementsByTagName("iframe"), frame, i;
// for (i = 0; i < frames.length; i += 1) {
// frame = frames[i];
// if (myIndexOf(
// event.source.location.pathname,
// frame.getAttribute("src").split("?")[0]
// ) < 0) {
// frame.contentWindow.postMessage(event.data, "*");
// }
// }
// };
//
var
mapUrl
=
function
(
url
)
{
// var searchString = url.href.split("?")[1],
// fileToDisplay;
//
// if (searchString) {
// fileToDisplay = getParameter(searchString, "file");
//
// if (fileToDisplay) {
var
param1
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
""
},
storage
:
{
href
:
'
browser://browse/ls/
'
},
preview
:
{
href
:
'
preview_by_hash_change.html
'
},
}}));
var
generateUuid
=
function
()
{
var
S4
=
function
()
{
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
"
0
"
+
string
;
}
return
string
;
};
return
S4
()
+
S4
();
};
var
param2
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
""
},
storage
:
{
href
:
'
browser://browse/ss/
'
},
preview
:
{
href
:
'
preview_by_postmessage.html
'
},
}}));
var
setup
=
function
()
{
// this will have to run automatically should renderJs have an easy API
var
instance1
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
''
},
// not sure if scope should be passed as a link or JSON parameter
scope
:
{
href
:
'
browser://browse/ls/
'
},
target
:
{
href
:
'
preview_by_hash_change.html
'
},
call
:
{
href
:
''
}
}}));
$
(
"
body
"
).
append
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
'
filebrowser_and_preview.html
'
+
"
?file=
"
+
param1
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
var
instance2
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
''
},
scope
:
{
href
:
'
browser://browse/ss/
'
},
target
:
{
href
:
'
preview_by_postmessage.html
'
},
call
:
{
href
:
''
}
}}));
$
(
"
body
"
).
append
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
'
filebrowser_and_preview.html
'
+
"
?file=
"
+
param2
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
$
(
"
body
"
).
append
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
'
filebrowser_and_preview.html
'
+
"
?file=
"
+
instance1
+
'
" id="
'
+
generateUuid
()
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
// } else {
// $("body").text("No parameter found in url");
// }
// } else {
// $("body").text("No parameter found in url (2)");
// }
$
(
"
body
"
).
append
(
'
<iframe src="
'
+
// XXX Hardcoded gadget to load
'
filebrowser_and_preview.html
'
+
"
?file=
"
+
instance2
+
'
" id="
'
+
generateUuid
()
+
'
">
'
+
'
<p>Your browser does not support iframes.</p>
'
+
'
</iframe">
'
);
};
$
(
document
).
ready
(
function
()
{
mapUrl
(
window
.
location
);
// if (window.addEventListener){
// window.addEventListener("message", handler, false)
// } else {
// window.attachEvent("onmessage", handler)
// }
setup
();
});
}(
document
,
jQuery
));
gadget/preview.html
0 → 100644
View file @
8a1e595d
<!DOCTYPE html>
<html>
<head>
<title>
Preview
</title>
<meta
name=
"viewport"
content=
"width=device-width, height=device-height, initial-scale=1"
/>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
/>
<script
type=
"text/javascript"
src=
"http://code.jquery.com/jquery-1.9.1.min.js"
></script>
<script
type=
"text/javascript"
src=
"../hyperbrowser.js"
></script>
<script
type=
"text/javascript"
src=
"../renderjs.js"
></script>
<script
type=
"text/javascript"
src=
"preview.js"
></script>
</head>
<body>
<noscript>
Please enable Javascript
</noscript>
</body>
</html>
\ No newline at end of file
gadget/preview.js
0 → 100644
View file @
8a1e595d
// > grab URL with parameters of file to open
// > call addGadget with those parameters?
// > display a file from some storage (local/session)
// > storage type will also be a parameter in the url?
// return "browser://localstorage/foo"
// file=browser%3A%2F%2Flocalstorage%2Ffoo
/*global document, jQuery */
"
use strict
"
;
(
function
(
document
,
$
)
{
var
ajaxGet
=
function
(
src
,
cb
)
{
$
.
ajax
({
method
:
'
GET
'
,
url
:
src
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
cb
(
value
,
textStatus
,
jqXHR
);
}
});
};
var
handler
=
function
(
event
)
{
ajaxGet
(
event
.
data
,
function
(
value
,
status
,
jqXHR
)
{
ajaxGet
(
value
.
_links
.
enclosure
.
href
,
function
(
value
,
status
,
jqXHR
)
{
if
(
value
===
""
)
{
window
.
document
.
body
.
innerHTML
=
"
file not found
"
;
}
else
{
window
.
document
.
body
.
innerHTML
=
value
;
}
});
});
}
var
mapUrl
=
function
(
url
)
{
var
searchString
=
url
.
href
.
split
(
"
?
"
)[
1
],
fileToDisplay
;
if
(
searchString
)
{
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
);
if
(
fileToDisplay
)
{
$
.
ajax
({
method
:
'
GET
'
,
url
:
fileToDisplay
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
if
(
value
===
""
)
{
$
(
this
).
text
(
"
file not found
"
);
}
else
{
$
(
this
).
text
(
value
);
}
},
});
}
}
else
{
$
(
this
).
text
(
"
no file to display
"
);
}
};
var
getParameter
=
function
(
searchString
,
paramName
)
{
var
i
,
val
,
params
=
searchString
.
split
(
"
&
"
);
for
(
i
=
0
;
i
<
params
.
length
;
i
++
)
{
val
=
params
[
i
].
split
(
"
=
"
);
if
(
val
[
0
]
==
paramName
)
{
return
decodeURIComponent
(
val
[
1
]);
}
}
return
null
;
};
$
(
document
).
ready
(
function
()
{
// mapUrl(window.location);
if
(
window
.
addEventListener
){
window
.
addEventListener
(
"
message
"
,
handler
,
false
)
}
else
{
window
.
attachEvent
(
"
onmessage
"
,
handler
)
}
});
}(
document
,
jQuery
));
\ No newline at end of file
gadget/preview_by_hash_change.js
View file @
8a1e595d
...
...
@@ -83,6 +83,10 @@
}
else
{
window
.
attachEvent
(
"
onmessage
"
,
handler
)
}
// $(window).on('hashchange', function() {
// console.log("LE HASH CHANGED");
// });
// $(window).trigger("hashchange");
});
}(
document
,
jQuery
));
\ No newline at end of file
gadget/preview_by_postmessage.js
View file @
8a1e595d
// > grab URL with parameters of file to open
// > call addGadget with those parameters?
// > display a file from some storage (local/session)
// > storage type will also be a parameter in the url?
// return "browser://localstorage/foo"
// file=browser%3A%2F%2Flocalstorage%2Ffoo
/*global document, jQuery */
"
use strict
"
;
(
function
(
document
,
$
)
{
...
...
@@ -24,44 +17,21 @@
};
var
handler
=
function
(
event
)
{
ajaxGet
(
event
.
data
,
function
(
value
,
status
,
jqXHR
)
{
ajaxGet
(
value
.
_links
.
enclosure
.
href
,
function
(
value
,
status
,
jqXHR
)
{
if
(
value
===
""
)
{
window
.
document
.
body
.
innerHTML
=
"
file not found
"
;
}
else
{
window
.
document
.
body
.
innerHTML
=
value
;
}
});
});
}
var
mapUrl
=
function
(
url
)
{
var
searchString
=
url
.
href
.
split
(
"
?
"
)[
1
],
fileToDisplay
;
if
(
searchString
)
{
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
);
if
(
fileToDisplay
)
{
$
.
ajax
({
method
:
'
GET
'
,
url
:
fileToDisplay
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
if
(
value
===
""
)
{
$
(
this
).
text
(
"
file not found
"
);
}
else
{
$
(
this
).
text
(
value
);
}
},
var
type
=
event
.
data
.
type
,
method
=
type
?
type
.
split
(
"
/
"
)[
0
]
:
undefined
;
// prevent both renderJs and page events triggering on "run"
if
(
type
===
undefined
||
method
!==
"
run
"
)
{
ajaxGet
(
event
.
data
,
function
(
value
,
status
,
jqXHR
)
{
ajaxGet
(
value
.
_links
.
enclosure
.
href
,
function
(
value
,
status
,
jqXHR
)
{
if
(
value
===
""
)
{
window
.
document
.
body
.
innerHTML
=
"
file not found
"
;
}
else
{
window
.
document
.
body
.
innerHTML
=
value
;
}
});
}
}
else
{
$
(
this
).
text
(
"
no file to display
"
);
});
}
}
;
}
var
getParameter
=
function
(
searchString
,
paramName
)
{
var
i
,
val
,
params
=
searchString
.
split
(
"
&
"
);
...
...
@@ -75,8 +45,58 @@
return
null
;
};
$
(
document
).
ready
(
function
()
{
// mapUrl(window.location);
var
mapUrl
=
function
(
searchString
)
{
var
fileToDisplay
=
getParameter
(
searchString
,
"
file
"
),
scope
,
register
,
service
;
if
(
fileToDisplay
)
{
$
.
ajax
({
method
:
'
GET
'
,
url
:
fileToDisplay
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
scope
=
value
.
_links
.
scope
.
href
.
slice
(
0
,
-
1
).
split
(
/
[/]
+/
).
pop
();
register
=
value
.
_links
.
call
.
href
.
replace
(
"
{method}
"
,
"
register
"
)
.
replace
(
"
{scope}
"
,
scope
)
.
replace
(
"
{interaction}
"
,
""
);
service
=
{
"
type
"
:
"
service/test
"
,
"
src
"
:
encodeURIComponent
(
window
.
location
.
href
),
"
rel
"
:
"
preview
"
,
"
self
"
:
window
.
frameElement
.
id
};
$
.
ajax
({
method
:
'
POST
'
,
url
:
register
,
context
:
$
(
this
),
data
:
JSON
.
stringify
(
service
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
registration failed:
"
+
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
// console.log("registration successful");
}
});
}
});
}
}
$
(
document
).
ready
(
function
()
{
var
search
=
window
.
location
.
search
;
if
(
search
)
{
mapUrl
(
search
.
slice
(
1
));
}
else
{
$
(
"
body
"
).
text
(
"
No parameter found in url
"
);
}
if
(
window
.
addEventListener
){
window
.
addEventListener
(
"
message
"
,
handler
,
false
)
...
...
renderjs.js
View file @
8a1e595d
...
...
@@ -9,6 +9,7 @@
// to publish their services
// -> find a way to prevent a gadget from reloading a plugin that's already
// active on the page
// -> for browser history, we would have to change the URL with a hash
// DISCUSSION POINTS:
...
...
@@ -466,6 +467,8 @@
"
options
"
:
{
// passing "options":options will procude a DataCloneError, so
// this is the only way (it seems) to pass the options object.
// beware frameElement does not work in cors, so actually
// THIS NEEDS A FIX!
"
parentFrame
"
:
window
.
frameElement
.
getAttribute
(
"
id
"
),
"
id
"
:
options
.
id
,
"
src
"
:
options
.
src
,
...
...
@@ -509,6 +512,7 @@
"
directories
"
:
spec
.
src
||
[],
"
map
"
:
[]
};
// listen for service postings to THIS renderJs instance
if
(
window
.
addEventListener
){
window
.
addEventListener
(
"
message
"
,
priv
.
serviceHandler
,
false
)
...
...
@@ -556,6 +560,8 @@
priv
.
returnResult
(
event
);
break
;
}
}
else
{
// no matching type!
}
};
...
...
@@ -578,14 +584,79 @@
// => run a service and post the result
priv
.
runService
=
function
(
event
)
{
var
result
=
window
[
event
.
data
.
service
].
apply
(
this
,
event
.
data
.
parameters
)
;
var
result
;
window
.
top
.
postMessage
({
"
type
"
:
"
result
"
,
"
result
"
:
result
,
"
trackingId
"
:
event
.
data
.
trackingId
,
"
callbackId
"
:
event
.
data
.
callbackId
,
},
event
.
origin
);
// URL handling
if
(
event
.
data
.
url
)
{
// let's go
$
.
ajax
({
url
:
event
.
data
.
parameters
[
0
],
method
:
'
GET
'
,
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
could not run service/interaction:
"
+
errorThrown
);
},
success
:
function
(
value
,
textStatus
,
jqXHR
)
{
$
.
ajax
({
method
:
'
GET
'
,
url
:
value
.
_links
.
enclosure
.
href
,
context
:
$
(
'
body
'
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
$
(
this
).
text
(
errorThrown
);
},
success
:
function
(
value2
,
textStatus
,
jqXHR
)
{
// this should be a deferred callback....
if
(
value
===
""
)
{
window
.
document
.
body
.
innerHTML
=
"
file not found
"
;
}
else
{
window
.
document
.
body
.
innerHTML
=
value2
;
}
}
});
}
});
}
else
{
result
=
window
[
event
.
data
.
service
].
apply
(
this
,
event
.
data
.
parameters
);
// only callback if we have to - should also be done via AJAX
if
(
event
.
data
.
callbackId
)
{
window
.
top
.
postMessage
({
"
type
"
:
"
result
"
,
"
result
"
:
result
,
"
trackingId
"
:
event
.
data
.
trackingId
,
"
callbackId
"
:
event
.
data
.
callbackId
,
},
event
.
origin
);
}
}
};
// => construct an iFrame selector from an array of ids
priv
.
assembleSelectorForService
=
function
(
selector
)
{
var
targetWindow
;
// for plain nested gadgets (no iFrame/sandbox) this will return
// only an empty array
// for iFrames/sandbox, selector will be an array of ids from
// which we have to construct our window element like so:
// http://bit.ly/12m3wJD
// http://mzl.la/17EeDiN
// final selector should look like this:
// window.frames["3a6b8d97"].contentWindow
// .frames["d63aca68"].contentWindow
// .frames["foo"].contentWindow
if
(
selector
.
length
===
0
)
{
targetWindow
=
window
;
}
else
{
try
{
targetWindow
=
selector
.
reduce
(
function
(
tgt
,
o
)
{
return
tgt
&&
o
[
1
]
?
tgt
.
frames
[
0
]
:
tgt
.
frames
[
o
[
0
]].
contentWindow
||
tgt
.
frames
[
o
[
0
]];
},
window
);
}
catch
(
error
)
{
console
.
log
(
error
);
}
}
return
targetWindow
;
};
// => request a service provided by a gadget
...
...
@@ -595,10 +666,14 @@
event
.
data
.
type
.
split
(
"
/
"
)[
1
]
),
selector
,
targetWindow
;
targetWindow
,
options
;
if
(
callService
)
{
// services are stored by URL (not id), so we need to find the service
// services are stored by URL (not id), because if inside an iFrame
// we cannot access the frame id, because of CORS.
// The only accessible parameter is the window.location.href URL, so
// services need to be stored with URL.
// in our gadget tree by using the URL provided by the service...
// and return an id path, so we can create a selector
selector
=
priv
.
constructSelectorForService
(
...
...
@@ -607,44 +682,41 @@
[]
);
// for plain nested gadgets (no iFrame/sandbox) this will return
// only an empty array
// for iFrames/sandbox, selector will be an array of ids from
// which we have to construct our window element like so:
// http://bit.ly/12m3wJD
// http://mzl.la/17EeDiN
// final selector should look like this:
// window.frames["3a6b8d97"].contentWindow
// .frames["d63aca68"].contentWindow
// .frames["foo"].contentWindow
if
(
selector
.
length
===
0
)
{
targetWindow
=
window
;
}
else
{
try
{
targetWindow
=
selector
.
reduce
(
function
(
tgt
,
o
)
{
return
tgt
&&
o
[
1
]
?
tgt
.
frames
[
0
]
:
tgt
.
frames
[
o
[
0
]].
contentWindow
||
tgt
.
frames
[
o
[
0
]];
},
window
);
}
catch
(
error
)
{
console
.
log
(
error
);
}
}
// and request the service
targetWindow
.
postMessage
({
options
=
{
"
type
"
:
"
run
"
,
"
trackingId
"
:
trackingId
,
"
callbackId
"
:
event
.
data
.
callbackId
,
"
service
"
:
event
.
data
.
service
,
"
parameters
"
:
event
.
data
.
parameters
},
event
.
origin
);
"
parameters
"
:
event
.
data
.
parameters
,
"
url
"
:
callService
.
url
||
undefined
}
// we should not directly postMessage...
if
(
callService
.
url
===
""
)
{
targetWindow
=
priv
.
assembleSelectorForService
(
selector
);
targetWindow
.
postMessage
(
options
,
event
.
origin
);
}
else
{
// we need the selector array to construct our targetWindow
// because we cannot pass a window object through an ajax call...
options
.
selector
=
selector
;
// let's go
$
.
ajax
({
url
:
callService
.
url
,
method
:
'
POST
'
,
data
:
JSON
.
stringify
(
options
),
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
console
.
log
(
"
call to targetWindow failed:
"
+
errorThrown
);
},
// success: function (value, textStatus, jqXHR) {
// console.log("call to targetWindow successful");
// }
});
}
}
};
// => check whether a service is available
priv
.
findServiceInMap
=
function
(
requestedService
,
scope
)
{
// scope... use for ???
var
i
,
service
,
passback
=
null
;
...
...
@@ -652,7 +724,13 @@
for
(
i
=
0
;
i
<
that
.
gadgetService
.
map
.
length
;
i
+=
1
)
{
service
=
that
.
gadgetService
.
map
[
i
];
if
(
service
.
rel
===
requestedService
)
{
passback
=
service
;
if
(
scope
)
{
if
(
scope
===
service
.
scope
)
{
passback
=
service
;
}
}
else
{
passback
=
service
;
}
}
}
return
passback
;
...
...
@@ -678,16 +756,6 @@
// => register gadget in index and tree
priv
.
registerGadget
=
function
(
data
,
options
)
{
// create index
if
(
that
.
gadgetIndex
===
undefined
)
{
priv
.
createGadgetIndex
();
}
// create tree
if
(
that
.
gadgetTree
===
undefined
)
{
priv
.
createGadgetTree
();
}
// index ~ cache
priv
.
addGadgetToIndex
(
data
,
options
);
...
...
@@ -713,7 +781,8 @@
options
=
{
"
rel
"
:
service
[
j
].
rel
,
"
type
"
:
service
[
j
].
type
,
"
src
"
:
service
[
j
].
src
||
window
.
location
.
href
.
split
(
"
?
"
)[
0
]
"
src
"
:
service
[
j
].
src
||
window
.
location
.
href
.
split
(
"
?
"
)[
0
],
"
url
"
:
""
};
$
(
root
).
addService
(
options
);
}
...
...
@@ -800,7 +869,8 @@
"
src
"
:
element
.
getAttribute
(
"
src
"
)
||
window
.
location
.
href
.
split
(
"
?
"
)[
0
],
"
type
"
:
element
.
getAttribute
(
"
type
"
),
"
rel
"
:
element
.
getAttribute
(
"
rel
"
)
"
rel
"
:
element
.
getAttribute
(
"
rel
"
),
"
url
"
:
""
});
}
break
;
...
...
@@ -895,6 +965,12 @@
// configuration or to retrieve the root when inside an iFrame
var
spec
=
priv
.
mapUrlString
(
window
.
location
.
search
);
// create index
priv
.
createGadgetIndex
();
// create tree
priv
.
createGadgetTree
();
// all instances of renderJs should have an serviceMap
priv
.
createServiceMap
(
spec
);
...
...
@@ -932,19 +1008,22 @@
callback
=
deferred
;
// store callback to be retrieved by response handler
priv
.
trackCallback
(
callbackId
,
callback
,
callbackFunction
);
if
(
callbackFunction
)
{
priv
.
trackCallback
(
callbackId
,
callback
,
callbackFunction
);
// set a deferred, so the callback can run when everything is done
deferred
.
done
(
function
(
result
,
callbackFunction
)
{
if
(
callbackFunction
)
{
callbackFunction
(
result
);
}
});
options
.
callbackId
=
callbackId
;
}
// set type
if
(
options
.
type
===
undefined
)
{
options
.
type
=
"
request/any
"
;
}
deferred
.
done
(
function
(
result
,
callbackFunction
)
{
if
(
callbackFunction
)
{
callbackFunction
(
result
);
}
});
options
.
callbackId
=
callbackId
;
window
.
top
.
postMessage
(
options
,
window
.
location
.
href
);
};
...
...
@@ -1088,7 +1167,18 @@
browse_ss_file_regexp
=
/^browser:
\/\/
browse
\/
ss
\/([\w\W]
+
)
/
,
browse_ss_directory_regexp
=
/^browser:
\/\/
browse
\/
ss
\/
/
,
plumb_regexp
=
/^browser:
\/\/
plumb
\/([\w\W]
+
)\/
/
,
key
;
// internal API (scope, interaction are optional)
// child > parent = call/{method}/{scope}/{interaction}/
// parent > child = delegate/{method}/{scope}/{interaction}/
// gadget > global = request/{method}/{scope}/{interaction}/
call_regexp
=
/^browser:
\/\/
call
\/([\w\W]
+
)\/
/
,
delegate_regexp
=
/^browser:
\/\/
delegate
\/([\w\W]
+
)\/
/
,
request_regexp
=
/^browser:
\/\/
request
\/([\w\W]
+
)\/
/
,
// vars
key
,
config
,
provider
,
param
,
value
,
targetWindow
;
// localStorage handler
if
(
ls_regexp
.
test
(
this
.
url
))
{
key
=
ls_regexp
.
exec
(
this
.
url
)[
1
];
if
(
this
.
method
===
"
POST
"
)
{
...
...
@@ -1130,6 +1220,7 @@
'
Content-Type
'
:
'
application/hal+json
'
},
JSON
.
stringify
(
response
));
// Session storage handler
}
else
if
(
ss_regexp
.
test
(
this
.
url
))
{
key
=
ss_regexp
.
exec
(
this
.
url
)[
1
];
if
(
this
.
method
===
"
POST
"
)
{
...
...
@@ -1162,22 +1253,20 @@
contents
:
[],
}
};
for
(
var
key
in
sessionStorage
){
response
.
_links
.
contents
.
push
({
href
:
'
browser://browse/ss/
'
+
key
});
}
this
.
respond
(
200
,
{
'
Content-Type
'
:
'
application/hal+json
'
},
JSON
.
stringify
(
response
));
}
else
if
(
plumb_regexp
.
test
(
this
.
url
))
{
console
.
log
(
"
PLUMB
"
);
key
=
plumb_regexp
.
exec
(
this
.
url
)[
1
];
if
(
this
.
method
===
"
POST
"
)
{
if
(
key
===
"
parentwindow
"
)
{
// XXX hardcoded * necessarity to send in case of file URL
// Fix needed!!!
// as before...
window
.
parent
.
postMessage
(
this
.
requestBody
,
"
*
"
);
this
.
respond
(
204
,
{},
""
);
}
else
{
...
...
@@ -1186,6 +1275,107 @@
}
else
{
this
.
respond
(
405
,
{},
""
);
}
// this looks up requests inside renderJs and
// triggers the respective postMessage
// should we use the key here or not and maybe pass the scope
// as parameter of the service object?
}
else
if
(
request_regexp
.
test
(
this
.
url
))
{
// key = request_regexp.exec(this.url)[1];
if
(
this
.
method
===
"
POST
"
)
{
// if (key === "map") {
config
=
JSON
.
parse
(
this
.
requestBody
);
var
options
=
{
"
type
"
:
"
request/
"
+
config
.
scope
,
"
service
"
:
config
.
service
,
"
parameters
"
:
config
.
parameters
};
window
.
postMessage
(
options
,
"
*
"
);
this
.
respond
(
204
,
{},
""
);
//} else {
// this.respond(404, {}, "");
//}
}
else
{
this
.
respond
(
405
,
{},
""
);
}
// this handles communication from child > parent
// using browser://call/{method}/{interaction/service}
}
else
if
(
call_regexp
.
test
(
this
.
url
))
{
param
=
call_regexp
.
exec
(
this
.
url
)[
1
].
split
(
"
/
"
)
key
=
param
[
0
];
value
=
param
[
1
];
if
(
this
.
method
===
"
POST
"
)
{
if
(
key
===
"
register
"
)
{
// still inside child frame
// add to tree, so lookup is possible when service is requested
config
=
JSON
.
parse
(
this
.
requestBody
);
window
.
parent
.
postMessage
({
"
type
"
:
"
tree/update
"
,
"
options
"
:
{
"
id
"
:
config
.
self
,
"
src
"
:
config
.
src
,
"
children
"
:
[]
}
},
"
*
"
);
// generate a url to be called once the service is requested
// this is a parent > child URL, so we delegate
// Need provider and rel here, because later we can remove
// from data being sent along with this URL
provider
=
config
.
self
||
"
any
"
;
// update config
config
.
url
=
'
browser://delegate/
'
+
provider
+
'
/
'
+
config
.
rel
config
.
scope
=
value
||
"
any
"
;
// register service
window
.
parent
.
postMessage
(
config
,
"
*
"
);
this
.
respond
(
204
,
{},
""
);
}
else
if
(
key
===
"
service
"
)
{
// inside child frame, request service to be run
var
sendToParent
=
"
data://application/hal+json;base64,
"
+
window
.
btoa
(
JSON
.
stringify
({
_links
:
{
self
:
{
href
:
this
.
url
},
request
:
{
href
:
this
.
requestBody
}
}}));
window
.
parent
.
postMessage
(
sendToParent
,
"
*
"
);
}
else
{
this
.
respond
(
404
,
{},
""
);
}
}
else
{
this
.
respond
(
405
,
{},
""
);
}
// this handles communication from parent > child
// using browser://delegate/{window_id}/{interaction/service}
// the id is only to reconfirm, because for nested windows, we need
// to reconstruct the complate selector
}
else
if
(
delegate_regexp
.
test
(
this
.
url
))
{
// key = delegate_regexp.exec(this.url)[1];
if
(
this
.
method
===
"
POST
"
)
{
// if (key === "map") {
config
=
JSON
.
parse
(
this
.
requestBody
);
// get the target
targetWindow
=
priv
.
assembleSelectorForService
(
config
.
selector
);
// cleanup
delete
config
.
selector
;
// post, this will call both the internal and on page handler!
targetWindow
.
postMessage
(
config
,
"
*
"
);
this
.
respond
(
204
,
{},
""
);
// } else {
// this.respond(404, {}, "");
// }
}
else
{
this
.
respond
(
405
,
{},
""
);
}
}
else
{
this
.
respond
(
404
,
{},
""
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment