Hi everyone,
Does anyone ever hear of a SMP (or marc2003's jscript) code for an library search toolbar (like the Quicksearch toobar component for example?)
There used to be a WSH toolbar in one of Br3tt's theme (xchange I think) but it's kind of old and I'm not sure I will be able to port it to SMP.
Not sure it helps, but here is an adaptation of the script I wrote for my config. It was not meant to work in a component-like fashion, so you might have to edit the code here and there (no window properties, sorry). My coding is much more naive than marc2003's or Br3tt's, but perhaps this makes it easier to grasp and modify.
For reasons I don't understand, it only works with columns ui, maybe some more advanced coder can figure out why,
I still didn't find the time to handle the typing animation when the text's length exceeds that of the width of the panel, so make sure the panel is wide enough for your average search strings.
Search results are displayed in a playlist called "Search results [your search string]", which is overwritten at every new search.
"use strict";
include(fb.ComponentPath + "docs\\flags.js");
include(fb.ComponentPath + "docs\\helpers.js");
include(fb.ComponentPath + "samples\\complete\\js\\lodash.min.js");
var font_height = 18;
var fontcolor = colours.White;
var text = "";
var cursor = 0;
var set_cursor = false;
var selection_lx = 0;
var selection_rx = 0;
var selection = "";
var mouse_lbtn_down = false;
var count = 0;
var timerID;
var timer = false;
var edit = false;
var writing = false;
var ctrla = false;
var dblclk = false;
var dblclk_lx = 0;
var dblclk_rx = 0;
var mouse_lbtn_down_x = 0;
var mouse_move_x = 0;
var obj = new ActiveXObject("htmlfile");
var autocomplete = new Array();
var history = new Array();
history.push(text);
var currentState = 0;
var ww = 0;
var wh = 0;
var text_x = 0;
function on_size(){
ww = window.Width;
wh = window.Height;
}
function on_paint(gr){
var iconfont = "Segoe mdl2 assets";
var font = gdi.Font(iconfont, font_height, 0);
var selection_color = colours.Black;
var icon = String.fromCharCode(57492);
var textheigth = gr.CalcTextHeight(icon, font);
text_x = wh + gr.CalcTextWidth(" ", font);
dblclk_lx = Math.max(text.slice(0, getPos(mouse_lbtn_down_x, text, font, gr)).toString().lastIndexOf(" ") + 1, 0);
dblclk_rx = getPos(mouse_lbtn_down_x, text, font, gr) + (text + " ").slice(getPos(mouse_lbtn_down_x, text, font, gr)).toString().indexOf(" ") + 1;
selection_lx = getPos(Math.min(mouse_lbtn_down_x, mouse_move_x), text, font, gr);
selection_rx = getPos(Math.max(mouse_lbtn_down_x, mouse_move_x), text, font, gr);
if (dblclk) selection_lx = Math.min(selection_lx, dblclk_lx);
if (dblclk) selection_rx = Math.max(selection_rx, dblclk_rx);
if (ctrla) selection_lx = 0;
if (ctrla) selection_rx = text.length;
var selection_x = text_x + (gr.CalcTextWidth(text.slice(0, selection_lx), font));
var selection_w = gr.CalcTextWidth(text.slice(selection_lx, selection_rx), font);
var text1 = text.slice(0, selection_lx);
var text2 = text.slice(selection_lx, selection_rx);
var text3 = text.slice(selection_rx);
if (set_cursor) {
cursor = getPos(mouse_lbtn_down_x, text, font, gr);
set_cursor = false;
}
selection = text2;
var cursor_x = text_x + gr.CalcTextWidth(text.slice(0, cursor), font);
gr.DrawRect(0, 0, ww - 1, wh - 1, 1, fontcolor);
gr.GdiDrawText(icon, font, fontcolor, 0, 0, wh, wh, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
gr.FillSolidRect(selection_x, (wh - textheigth)/2, selection_w, textheigth, colours.Gray);
gr.GdiDrawText(text1, font, fontcolor, text_x, 0, gr.CalcTextWidth(text1, font), wh, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
gr.GdiDrawText(text2, font, selection_color, text_x + gr.CalcTextWidth(text1, font), 0, gr.CalcTextWidth(text2, font), wh, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
gr.GdiDrawText(text3, font, fontcolor, text_x + gr.CalcTextWidth(text1, font) + gr.CalcTextWidth(text2, font), 0, gr.CalcTextWidth(text3, font), wh, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
if (selection_w == 0 && edit && count%2 == 1) gr.DrawLine(cursor_x, (wh - textheigth)/2, cursor_x, (wh + textheigth)/2, 1, fontcolor);
if (text == "" && !edit) gr.GdiDrawText("Search", font, fontcolor, text_x, 0, ww - text_x, wh, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
writing = false;
}
function on_mouse_move(x, y){
window.SetCursor(IDC_IBEAM);
if (mouse_lbtn_down){
mouse_move_x = x;
window.Repaint();
}
}
function on_mouse_lbtn_down(x, y){
edit = true;
mouse_lbtn_down = true;
mouse_lbtn_down_x = x;
set_cursor = true;
unselect();
window.Repaint();
}
function on_mouse_lbtn_up(x, y){
mouse_lbtn_down = false;
}
function on_mouse_lbtn_dblclk(x, y){
mouse_lbtn_down = true;
mouse_lbtn_down_x = x;
dblclk = true;
window.Repaint();
}
function on_mouse_leave(){
mouse_lbtn_down = false;
edit = writing;
}
function on_focus(is_focused){
if (is_focused){
timerID = window.SetInterval(function() {
count++;
window.Repaint();
}, 500);
timer = true
} else {
window.ClearInterval(timerID);
timer = false;
count = 0;
window.Repaint();
}
}
function on_char(code){
if (code > 31) {
if (selection_lx < selection_rx){
text = text.slice(0, selection_lx) + String.fromCharCode(code) + text.slice(selection_rx);
cursor = selection_lx + 1;
unselect();
} else {
text = text.slice(0, cursor) + String.fromCharCode(code) + text.slice(cursor);
cursor = cursor + 1;
}
newState(text);
var autocompleteMenu = window.CreatePopupMenu();
var filtered_list = _.uniq(autocomplete, true).filter(filterAutocomplete);
for (var i = 0; i < filtered_list.length; i++){
autocompleteMenu.AppendMenuItem(MF_STRING, i + 1, filtered_list[i]);
}
var ret = autocompleteMenu.TrackPopupMenu(text_x, wh, 0);
if (ret > 0){
text = filtered_list[ret - 1];
cursor = text.length;
}
writing = true;
window.Repaint();
}
}
function on_key_down(vkey){
var ShiftKeyPressed = utils.IsKeyPressed(VK_SHIFT);
var ControlKeyPressed = utils.IsKeyPressed(VK_CONTROL);
if (!ControlKeyPressed){
switch (vkey){
case 8: //backspace
if (selection_lx < selection_rx){
text = text.slice(0, selection_lx) + text.slice(selection_rx);
cursor = selection_lx;
unselect();
} else {
text = text.slice(0, Math.max(cursor - 1, 0)) + text.slice(cursor);
cursor = Math.max(cursor - 1, 0);
}
newState(text);
break;
case 13: //enter
search();
text = "";
cursor = 0;
history = [];
newState(text);
break;
case 37: //left arrow
cursor = Math.max(cursor - 1, 0);
break;
case 39: //right arrow
cursor = Math.min(cursor + 1, text.length);
break;
case 46: //delete
if (selection_lx < selection_rx){
text = text.slice(0, selection_lx) + text.slice(selection_rx);
cursor = selection_lx;
unselect();
} else {
text = text.slice(0, cursor) + text.slice(cursor).slice(1);
}
newState(text);
break;
}
} else {
switch (vkey){
case 65: //ctrl + A
ctrla = true;
break;
case 67: //ctrl + C
obj.parentWindow.clipboardData.setData("Text", selection);
break;
case 86: //ctrl + V
var clipboard = obj.parentWindow.clipboardData.getData("Text") + "";
if (selection_lx < selection_rx){
text = text.slice(0, selection_lx) + clipboard + text.slice(selection_rx);
} else {
text = text.slice(0, cursor) + clipboard + text.slice(cursor);
}
cursor = selection_lx + clipboard.length;
unselect();
newState(text);
break;
case 88: //ctrl + X
obj.parentWindow.clipboardData.setData("Text", selection);
text = text.slice(0, selection_lx) + text.slice(selection_rx);
cursor = selection_lx;
unselect();
newState(text);
break;
case 89: //ctrl + Y
currentState = Math.max(currentState - 1, 0);
text = history[currentState];
cursor = text.length;
break;
case 90: //ctrl + Z
currentState = Math.min(currentState + 1, history.length - 1);
text = history[currentState];
cursor = text.length;
break;
}
}
window.Repaint();
}
function getPos(x, text, font, gr){
var pos;
for (var i = 0; i <= text.length; i++){
if (x < text_x + gr.CalcTextWidth(text.slice(0, i + 1), font)){
pos = i;
i = text.length + 1;
} else {
pos = text.length;
}
}
return pos;
}
function unselect(){
mouse_move_x = mouse_lbtn_down_x;
dblclk = false;
ctrla = false;
}
function newState(text){
history.slice(currentState);
history.unshift(text);
currentState = 0;
}
function search(){
autocomplete.push(text);
autocomplete.sort();
var SortOrder = "%album artist%|%release date%|%album%|%discnumber%|%set subtitle%|%tracknumber%|%path%";
try {
var queryItems = fb.GetQueryItems(fb.GetLibraryItems(), text);
}
catch(Error){
var queryItems = fb.CreateHandleList();
}
var index = -1;
for (var i = 0; i < plman.PlaylistCount; i++) {
if (plman.GetPlaylistName(i).indexOf("Search results [") == 0) index = i;
}
if (index > -1){
plman.RemovePlaylist(index);
} else {
index = plman.PlaylistCount;
}
plman.CreatePlaylist(index,"Search results [" + text + "]");
plman.InsertPlaylistItems(index, 0, queryItems);
plman.SortByFormat(index, SortOrder);
plman.ActivePlaylist = index;
}
function filterAutocomplete(value){
return value.indexOf(text) == 0;
}