Passing JavaScript variable into snippet - modx

I'm working on a search form for my ModX application that is consisted of a chunk and a snippet. What I'm trying to achieve is to pass what was entered into the search box into a javascript variable and then pass it to my snippet, however, the snippet receives the literal text, and not the value that I enter into the parameter when I call it.
I don't know if what I'm attempting is possible in ModX or if I need to take a different approach, but I would be hugely thankful for anyone who can provide any insight.
Chunk:
<script>
$('.search-btn').click(function() {
var search = $('.search-entry').val();
[[showSearchResults? &q=`search`]]
});
</script>
Snippet:
<?php
$search = $modx->getOption('q', $scriptProperties);
echo $search; // this always prints "search"
?>

I doubt that this code makes sense:
<script>
$('.search-btn').click(function() {
var search = $('.search-entry').val();
[[showSearchResults? &q=`search`]]
});
</script>
The snippet call returns the result of snippet's execution with param q always equal to the string 'search' in your case and finally on your page you will have something like this:
<script>
$('.search-btn').click(function() {
var search = $('.search-entry').val();
'search' // assuming your snippet just returns what has been passed to it.
});
</script>
In order to accomplish your task you can use a simple trick. Call your snippet like this:
[[!yourSnippet? &yourVar=`[[!#POST.yourVar]]` ]] // or GET
Lets say this snippet call is located on a page accessible via url /test/ on your server. So, now you just have to send the parameters you collected from your search form using AJAX to the /test/ page where your snippet is:
var yourVar = $('.search-entry').val();
$.ajax({
type: "POST",
url: "/test/",
data: {yourVar: yourVar},
success: success,
dataType: "html"
});
Hope it helps :)
PS If you want to search Resource content and TV content, I can highly recommend an extra called SimpleSearch.

Related

pretty url search string instead of question marks

I have been looking at other websites and see when you search, primary something like a search term, location and category you will see a pretty url like:
example.com/black-boots/new-york/shoes
instead of what I have now which is something like:
example.com/search-results/search?=black+boots&city=new+york&category=shoes
In my route I could start with something like:
router.get('/search-results/:search/:city/:category', shopController.getSearchResults);
And in the controller I could use req.params.city and so on to get the values from the url but the part that I can't figure out is a good way to get the text input values into the url using a get request.
Using GET by default gives me the 'ugly' looking url.
Basically the part that needs to go into the form
<form method="GET" action="/search-results/search/city/category">
Comments, plus this code sample for a GET request:
const form = document.getElementById('searchform');
form.addEventListener('submit', evt => {
const who = encodeURIComponent(document.getElementById('who').value);
const where = encodeURIComponent(document.getElementById('where').value);
const what = encodeURIComponent(document.getElementById('what').value);
window.location.href = `/${who}/${where}/${what}`;
}

After passing object to handlebars, how can I access that object in script tag?

I first get the data from sql then pass it into handlebars.
Inside the tag in .handlebars/using view.js, I want to access doctors, but i keep getting[object][object]. I tried json.stringifying it before but still no luck. What is the best way to do this?
umd.matchDocs(val2, function(data) {
console.log(data);
var renderDocs = {
doctors: data
}
res.render("dashboard", renderDocs);
});
After passing object to handlebars, how can I access that object in script tag?
No, not by default. But you can make the data available manually if you want.
Data you pass to handlebars rendering operation is available during the rendering operation only. If you want to be able to access some of that data later in client-side <script> tags, then you can "render" Javascript variables into the <script> tags that contain the desired data.
Remember when rendering data into Javascript variables, you need to render the actual Javascript text (converting to JSON will often create the text for you).
In your specific example, you could do something like this in your rendering code:
umd.matchDocs(val2, function(data) {
console.log(data);
var renderDocs = {
doctors: JSON.stringify(data)
}
res.render("dashboard", renderDocs);
});
And, then in the template:
<script>
var doctors = {{{doctors}}};
</script>
Then, this array of doctors would be available to the Javascript in your page.
In case you haven't seen the triple braces like shown above, that's to tell handlebars to skip any HTML escaping in the data (because this isn't HTML).

How to use Node.js to create modified versions of html documents?

I am trying to do this:
Read html document "myDocument.html" with Node
Insert contents of another html document named "foo.html" immediately after the open body tag of myDocument.html.
Insert contents of yet another html document named "bar.html" immediately before the close body tag of myDocument.html.
Save the modified version of "myDocument.html".
To do the above, I would need to search the DOM with Node to find the open and closing body tags.
How can this be done?
Very simply, you can use the native Filesystem module that comes with Node.JS. (var fs = require("fs")). This allows you to read and convert the HTML to a string, perform string replace functions, and finally save the file again by rewriting it.
The advantage is that this solution is completely native, and requires no external libraries. It is also completely faithful to the original HTML file.
//Starts reading the file and converts to string.
fs.readFile('myDocument.html', function (err, myDocData) {
fs.readFile('foo.html', function (err, fooData) { //reads foo file
myDocData.replace(/\<body\>/, "<body>" + fooData); //adds foo file to HTML
fs.readFile('bar.html', function (err, barData) { //reads bar file
myDocData.replace(/\<\/body\>/, barData + "</body>"); //adds bar file to HTML
fs.writeFile('myDocumentNew.html', myDocData, function (err) {}); //writes new file.
});
});
});
In a simple but not accurate way, you can do this:
str = str.replace(/(<body.*?>)/i, "$1"+read('foo.html'));
str = str.replace(/(<\/body>)/i, read('bar.html')+'$1');
It will not work if the myDocument content contains multiple "<body ..' or '</body>', e.g. in javascript, and also the foo.html and bar.html can not contains '$1' or '$2'...
If you can edit the content of myDocument, then you can leave some "placeholder" there(as html comments), like
<!--foo.html-->
Then, it's easy, just replace this "placeholder" .
Use the cheerio library, which has a simplified jQuery-ish API.
var cheerio = require('cheerio');
var dom = cheerio(myDocumentHTMLString);
dom('body').prepend(fooHTMLString);
dom('body').append(barHTMLString);
var finalHTML = dom.html();
And just to be clear since the legions of pro-regex individuals are already appearing in droves, yes you need a real parser. No you cannot use a regular expression. Read Stackoverflow lead developer Jeff Atwood's post on parsing HTML the Cthulhu way.

modified innerHTML does not show on page

I am writing a Google extension. Here my content script modifies a page based on a list of keywords requested from background. But the new innerHTML does not show up on the screen. I've kluged it with an alert so I can see the keywords before deciding to actually send a message, but it is not how the routine should work. Here's the code:
// MESSAGE.JS //
//alert("Message Page");
var keyWordList= new Array();
var firstMessage="Hello!";
var contentMessage=document.getElementById("message");
contentMessage.value=firstMessage;
var msgComments=document.getElementsByClassName("comment");
msgComments[1].value="Hello Worlds!";//marker to see what happens
chrome.extension.sendRequest({cmd: "sendKeyWords"}, function(response) {
keyWordList=response.keyWordsFound;
//alert(keyWordList.length+" key words.");//did we get any keywords back?
var keyWords="";
for (var i = 0; i<keyWordList.length; ++i)
{
keyWords=keyWords+" "+keyWordList[i];
}
//alert (keyWords);//let's see what we got
document.getElementsByClassName("comment")[1].firstChild.innerHTML=keyWords;
alert (document.getElementsByClassName("comment")[1].firstChild.innerHTML);// this is a band aid - keyWords does not show up in tab
});
document.onclick= function(event) {
//only one button to click in page
document.onload=self.close();
};
What do I have to do so that the text area that is modified actually appears in the tab?
(Answering my own question) This problem really has two parts. The simplest part is that I was trying to modify a text node by setting its value like this:
msgComments1.value="Hello Worlds!"; //marker to see what happens
To make it work, simply set the innerHTML to a string value like this:
msgComment1.innerHTML="Hello Worlds!"; //now it works.
The second part of the problem is that the asynchronous call to chrome.extension.sendRequest requires a callback to update the innerHTML when the reply is received. I posted a question in this regard earlier and have answered it myself after finding a solution in an previous post by #serg.

Chrome Extension iframe dom reference disqus

How do I get a reference to the dom of a cross domain iframe/frame?
I want to do some stuff to disqus comments with an extension.
My manifest has the following:
"all_frames": true,
"matches": ["*://*.disqus.com/*","*://disqus.com/*", "http://somesite.com"]
I am not trying to communicate outside of the frame - that is the js will take care of the work without needing to 'tell' me anything.
all_frames should inject the listed js files into every frame, no?
When I do this:
if (window != window.top){
alert('In an IFRAME: ' + window.location.href);
}
...I get the expected disqus URLs.
But when I do this:
var btnCommentBlock = document.getElementsByClassName('dsq-comment-buttons');
alert('btnCommentBlock length: ' + $(btnCommentBlock).length);
...I get 0 for length.
I updated my answer to Javascript to access Disqus comment textbox?
Basically, Disqus changed the selector. They no longer use textarea, they use contenteditable divs.
Something like this should work:
// We just need to check if the IFrame origin is from discus.com
if (location.hostname.indexOf('.disqus.com') != -1) {
// Extract the textarea (there must be exactly one)
var commentBox = document.querySelector('#comment');
if (commentBox) {
// Inject some text!
commentBox.innerText = 'Google Chrome Injected!';
}
}
Source Code:
https://gist.github.com/1034305
Woohoo! I found the answer on github:
https://gist.github.com/471999
The working code is:
$(document).ready(function() {
window.disqus_no_style = true;
$.getScript('http://sitename.disqus.com/embed.js', function() {
var loader = setInterval(function() {
if($('#disqus_thread').html().length) {
clearInterval(loader);
disqusReady();
}
}, 1000);
});
function disqusReady() {
//whatever you can imagine
}
});
I put this in the disqusReady() function:
var aTestHere = document.getElementsByClassName('dsq-comment-body');
alert(aTestHere[0].innerHTML);
...and got back the innerHTML as expected.
Mohamed, I'd really like to thank you for taking the time to interact with my question. If you hadn't posted that link to github there's no telling when if ever I'd have figured it out or found the other code.
edit: After a few minutes of experimenting it looks like it is not necessary to call getScript so you should be able to comment that out.
Also unnecessary is window.disqus_no_style so I commented that out too.
I'll experiment some more and update the answer later. One of those two things prevented me from being able to actually post a comment at the disqus site I use. //them out still allows access to the dom and the ability to post.

Resources